GTK Dialog constructor cannot be used to create instances of a subclass MessageDialog WTF - dialog

When I run the following code:
dialog = Gtk.MessageDialog.new(
None,
Gtk.DialogFlags.MODAL,
Gtk.MessageType.QUESTION,
Gtk.ButtonsType.YES_NO,
f'Do you really want to {action} "{data["list_element"].name}" ?',
)
I get this error:
Dialog constructor cannot be used to create instances of a subclass MessageDialog
What does it mean? How do I solve it?

I think the problem is the use of new, which seems to be reserved for the parent Gtk.Dialog class. From this source, it seems you can use the Gtk.MessageDialog constructor directly:
dialog = Gtk.MessageDialog(
None,
Gtk.DialogFlags.MODAL,
Gtk.MessageType.QUESTION,
Gtk.ButtonsType.YES_NO,
f'Do you really want to {action} "{data["list_element"].name}" ?',
)

Related

Python OOP method call

I have 2 different classes:
Automation and ClickElement
Window = Automation()
click_element = ClickElement()
In the class ClickElement is a method called 'by_span_name(name)'
Now i want to call the method in this way:
Window.click_element.by_span_name(name)
How do i do that?
If i try it like this way, Pycharm doesn´t suggest any class after the first dot of Window.click_elem... Does click_element have to inherit form Window?
You can add ClickElement as a composed object in Automation
Window = Automation()
Window.click_element = ClickElement()

How to avoid duplication of class instances in Python?

What is a good way to avoid duplication of a class instance when it is created using the __init__() function.
This question is a result of this issue.
Context (using employee class example):
Lets say I have an employee class: __init__(self,name,dept)
I also have a method, employee.info(self) that prints out name and dept of any employee.
However a user could just add an employee by calling a=employee(args..). They could do it multiple times using the same instance variable a, but different employee names.
This will cause issues if they try to print a.info(), as each time a different employee name will be printed.
Is there a better way to do this? I know it is possible to have the __init__() "pass" and define a new method to create an instance.
Expect results:
>>Adam=employee('marketing')
>>Adam.info()
>>Adam works in marketing.
OR
>>a=employee('Adam','marketing')
>>a=employee('Mary','marketing')
>>Error: employee instance with identifier "a" already exists.
>>Use employee.update() method to modify existing record.
Is there a cleaner way of doing it? (as you might guess, I am still learning python).
Or is it good practice to write an explicit function (instead of a class method) to add new employees?
what you try is impossible, because in
a=employee('Adam','marketing')
a is not an object but a variable that points to the object employee('Adam','marketing').
When you do
a=employee('Mary','marketing')
you say to python that now, a must now not point to the object employee('Adam','marketing') but to the object employee('Mary','marketing'). And then, if you have no more variable to reference the object employee('Adam','marketing'), the garbage collector will destroy it.
You must consider that in python all is object, but not the variables that are only references to manipulate objects.
I have been racking my brains over the same problem and have finally managed to figure out a workaround :
Create a dictionary that stores the employee name and the related object like this :
total_emp_dict = {}
Add this inside the def __init__ of the class employee : total_emp_dict[name] = self. This will ensure to add each employee name as key and the object associated will be added as value.
Now create a new function outside & before the employee class is defined, let's call it create_new_emp. It will go like this :
#function to check and avoid duplicate assignment of instances
def create_new_emp(name, dept):
if name in total_emp_dict:
return total_emp_dict[name]
else:
return employee(name, dept)
When creating a any new employee, use this new function : a = create_new_emp("Adam", HR) instead of a = employee("Adam", HR)
Explanation : This function will ensure that duplicate assignment is not done. If "a" is already assigned to "Adam", this function will return object of "Adam" to "a", when called again. But if nothing is assigned to "a", then this function will handover to the attributes (name, dept) to employee class and create a new instance. This instance will then be assigned to "a".
I don't know if this is the best solution for this problem, but honestly this is the only solution I have found so far and it works great for me without much fuss / extra code space. Hope it works for you too! :)

How to set property type of qml signal?

I am learning qml,quick and pyqt5 and write a small test script.
In this script, I want to drop something on my UI and print the url of it.
test.qml
import QtQuick 2.3
Rectangle {
id : root
signal clicked(int x, int y)
signal filedroped(list url)
width: 800
height: 450
MouseArea {
anchors.fill: parent
onClicked: {
parent.clicked(mouseX, mouseY)
}
DropArea {
anchors.fill: parent
onDropped: {
root.filedroped(drop.urls)
}
}
}
}
The doc says:Any of the QML Basic Types aside from the enumeration type can be used as custom property types.
But I got error like this in signal filedroped:
Invalid signal parameter type: list
Also, I have tried urllist and string.
urllist failed and string works.
What's wrong with my script?
EDIT
Since I use qml with pyqt, I do not want to use the type var.
With var, I'll got a QJSValue object instead of basic type of python in my python script.
Why qml performs different with the official document? Is the document wrong?
It seems on there's indeed an error in the Qt Documentation. It is said (here) that
the allowed parameter types [for signal parameters] are the same as those listed under
Defining Property Attributes on this page.
Yet one can define a property as follow:
property list<Item> items
whereas this is invalid:
signal mysignal(list<Item> items)
But anyway, the QML list type was not a solution. The official documentation is quite clear:
A list can only store QML objects, and cannot contain any basic type
values. (To store basic types within a list, use the var type
instead.).
In other words you can't use list to store strings, url, int. You have to use var. Another solution would be to use a formatted string with a custom separator instead of your url list, and split it on the Python side.
It looks that urllist is an array of urls so you can use var in this case:
signal filedroped(var urls)

How to modify safely CCLabelBMFont String after first allocation created?

I have a member named _label as an ivar member in class :
#interface CCHelloWorldLayer : CCLayer
{
CCLabelBMFont *_label;
}
in another codeblock: initializing with this line:
_label = [CCLabelBMFont labelWithString:#"Testing " fntFile:fntName];
question is this:
if I want to modify its text what Should I do ?
I dont see any method like:
[_label setString:#"Well.there is no such a method"];
if I do
_label = [CCLabelBMFont labelWithString:#"Testing " fntFile:fntName];
_label = [CCLabelBMFont labelWithString:#"Well.there is no such a method"
fntFile:fntName];
is first memory allocation autoreleasing it self ?
is it safe to recall labelWithString method repeately ?
(note:I dont use ARC in test project.and I wont.)
thanks in advice
There is a setString method but it appears to be "private". The +labelWithString method does create an autorelease object and can be used repeatedly. It looks like it creates a texture, so you would want to create a new texture each time (as opposed to trying to modify it).
In general though, if you want the autoreleased object to stick around, you should retain it and release it when you're done.
[_label setString:#"Well.there is no such a method"];
This method exists and you can call it like that. Try it, it works.
The method is not declared in the class but in CCLabelProtocol.

Masking QLineEdit text

I am using PyQt4 QLineEdit widget to accept password. There is a setMasking property, but not following how to set the masking character.
editor = QLineEdit()
editor.setEchoMode(QLineEdit.Password)
There is no setMasking property for QLineEdit in either PyQt4 or Qt4. Are you talking about setInputMask()? If you are, this does not do what you seem to think it does. It sets the mask against which to validate the input.
To get the control to hide what is typed, use the setEchoMode() method, which will (should) display the standard password hiding character for the platform. From what I can see from the documentation, if you want a custom character to be displayed, you will need to derive a new class. In general however, this is a bad idea, since it goes against what users expect to see.
It's quite easy using Qt: you would need to define a new style and return new character from the styleHint method whenever QStyle::SH_LineEdit_PasswordCharacter constant is queried. Below is an example:
class LineEditStyle : public QProxyStyle
{
public:
LineEditStyle(QStyle *style = 0) : QProxyStyle(style) { }
int styleHint(StyleHint hint, const QStyleOption * option = 0,
const QWidget * widget = 0, QStyleHintReturn * returnData = 0 ) const
{
if (hint==QStyle::SH_LineEdit_PasswordCharacter)
return '%';
return QProxyStyle::styleHint(hint, option, widget, returnData);
}
};
lineEdit->setEchoMode(QLineEdit::Password);
lineEdit->setStyle(new LineEditStyle(ui->lineEdit->style()));
now the problem is that pyqt doesn't seem to know anything about QProxyStyle; it seem to be not wrapped there, so you're stuck, unless you would want to wrap it yourself.
regards
As docs say http://doc-snapshot.qt-project.org/4.8/stylesheet-examples.html#customizing-qlineedit:
The password character of line edits that have QLineEdit::Password echo mode can be set using:
QLineEdit[echoMode="2"] {
lineedit-password-character: 9679;
}
In Qt Designer
Select the line edit, and in the Property Editor window, there will be a property echoMode which you can set to Password.
Using python code
In this case, Anti Earth's answer will work which is:
myLineEdit.setEchoMode(QLineEdit.Password)

Resources