PyQt check if value of qlabel changed - pyqt

I Need to check if the value (str) of a qlabel changed.
I think about using the following code (nearly the same as used by a spinbox widget in PyQt):
self.connect(self.ui.labelEntry, QtCore.SIGNAL("valueChanged(str)"), self.autovalidate)
What's the correct Methode to check if value changed?
All the best;

QLabels don't have a valueChanged/textChanged signal. You either have to use another widget type (a QLineEdit for instance) or to subclass QLabel and create your own change-aware class with a textChanged signal.
If you use QtDesigner, it might be simpler to go with the first solution and customize your QLineEdit from the Designer. In the property editor, unckeck frame, check readOnly, and write background-color:"transparent" in styleSheet and you've got a QLabel looking QLineEdit.
You also should use the new-style syntax, it's far more elegant.
self.ui.labelEntry.textChanged.connect(self.autovalidate)

Related

Get the contents of a widget in a layout in PyQt

I recently decided to create a small application that simply reads the files in a compressed file and renames them. I went through several UI modules and decided to use PyQt6.
To achieve this, I first created a QWidget that holds the widgets QPushButton and QLineEdit.
The user then types the new name into the QLineEdit widget and select the QPushButton if the file has to be excluded.
Now, this widget that was created will be added into a QVBoxLayout which is then set as the QScrollArea layout.
Here's my problem:
Once I was done creating the scroll area and the list, I wanted to retrieve the content of each widget. For this purpose, I use the findChild method. But it only returns the address of the object.
Is there any way to get the text stored in QLineEdit of each widget? Is it possible to retrieve the text just by knowing its address?
Here's what I tried:
for index in range(self.layout.count()):
widget = self.layout.itemAt(index).widget()
nameFromLineEdit = widget.findChild(QLineEdit).text()
print(nameFromLineEdit)

How to get list of widgets in pyqt?

I am designing a interface with QtDesigner and editing its functionalities with PyQt. One of the widgets that i created has several pushButtons and i want them all to have the property Checkable = True.
So currently what i am doing is:
class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
uic.loadUi('./my_widget.ui', self)
self.pushButton_X.setCheckable(True)
self.pushButton_Y.setCheckable(True)
self.pushButton_Z.setCheckable(True)
self.pushButton_ETC.setCheckable(True)
self.show()
Is there any way i can do something like:
pushbuttons_list = self.get_all_pushbuttons()
for i in pushbuttons_list:
i.setCheckable(True)
?
Im trying the answers to this question but i keep getting
> File "./testing_class.py", line 12, in __init__
items = (self.layout.itemAt(i) for i in range(self.layout.count()))
AttributeError: 'builtin_function_or_method' object has no attribute 'count'
Your example failed because all Qt properties can be accessed by calling the attribute (see the parentheses used for self.layout()):
items = (self.layout().itemAt(i) for i in range(self.layout().count()))
Note that this will only get access to the layout items, not the widgets they might (or might not) contain. For this, using comprehensions will only complicate things unnecessarily, as one-liners should be used only as long as they keep the code readable; the comprehension above is already complex enough, and since you will need to cycle through all items anyway, there's little use in it. Just use a for loop, which is far more readable:
for i in range(self.layout().count()):
widget = self.layout().itemAt(i).widget()
if isinstance(widget, QPushButton):
widget.setCheckable(True)
Note that if you have several buttons that you want checkable and you are doing this only to avoid manually setting the checkable property for all of them, you can just use the extended selection mode that is common for all UI elements that allow selection by keeping pressed Ctrl when clicking multiple objects.
The property editor will automatically show all common properties for the selected widgets, and apply the changed property to all of them.
Another option is to use findChildren():
for button in self.findChildren(QPushButton, Qt.FindDirectChildrenOnly):
button.setCheckable(True)
The Qt.FindDirectChildrenOnly flag is required whenever you have complex layouts that have nested widgets containing other buttons, if you remove that you will find any push button that exists inside the window (or the widget referenced as self).
Finally, buttons can be part of a QButtonGroup, which can also be created in Designer. Just select all buttons (as explained above), right click on one of them and select "Assign to button group", and then:
for button in self.buttonGroup.buttons():
button.setCheckable(True)
Note that the self.buttonGroup above is the object name assigned by Designer, if you change it or you create more than one, ensure that the reference matches it.

Make QTableWidgetItem non-editable, but still able to select parts of a string

I have a QTableWidget with data that I would like the user to be able to double-click on, and copy a specific part of the text. The only thing I want to disable is the user's ability to change that text, meaning that setting the flag ~Qt.ItemIsEditable is too restrictive. How can I achieve this in PyQt5?
Note: This solution works for all kinds of classes that inherit from QAbstractItemView like QTableWidget or QTreeWidget.
A possible solution is to use a modify the editor to be read-only through a delegate.
class StyledItemDelegate(QStyledItemDelegate):
def createEditor(self, *args):
editor = super().createEditor(*args)
if isinstance(editor, QLineEdit):
editor.setReadOnly(True)
return editor
delegate = StyledItemDelegate(view)
view.setItemDelegate(delegate)

PyQt: how to create a dialog as a child of another dialog

In PyQt, I have a dialog that spawns another dialog (when you click a button to do so in the first dialog). I want to maintain a strong parent-child relationship, for garbage collection purposes, and to make the .findChild and .findChildren functions usable.
The root of the question may be: how do you use .setParent() but still have the object in question be shown as a separate window, rather than shown within the parent widget?
The 'parent' dialog (actually a container widget within a tab within a dialog) is 'newEntryWidget'. It spawns 'clueDialog' when a signal (not shown here) calls newEntryWidget.quickTextClueAction as a slot. Visually, clueDialog should be a "top level window" with its own banner, its own window attributes (I want to keep it on top of everything else), etc.
class newEntryWidget(QWidget,Ui_newEntryWidget):
def __init__(self,parent,sec=0,formattedLocString='',fleet='',dev='',origLocString='',amendFlag=False,amendRow=None):
QDialog.__init__(self)
self.parent=parent # just an attribute; not the same as setParent
...
...
def quickTextClueAction(self):
self.newClueDialog=clueDialog(self,self.ui.timeField.text(),self.ui.teamField.text(),self.ui.radioLocField.text(),lastClueNumber+1)
self.newClueDialog.show()
class clueDialog(QDialog,Ui_clueDialog):
def __init__(self,parent,t,callsign,radioLoc,newClueNumber):
QDialog.__init__(self)
self.parent=parent # just an attribute; not the same as setParent
...
...
Right now, since I am using self.parent=parent, which is just an attribute and not true "parent/child relationship" in Qt terms, clueDialog does display as a top level window, which is what I want:
But, if I add 'self.setParent(parent)' in the clueDialog init function, I get this:
How can I preserve the top-level-window behavior, and have the real-honest-parent-child-relationship so that .findChild(clueDialog) will work from within the newEntryWidget object?
Ultimately, I want to enforce that the newEntryWidget object should not be closed if it still has and 'child' clueDialogs open.
Instead of calling .setParent, call QDialog.__init__(self, parent) which constructs the clue dialog with a parent from the beginning. Setting it this way allows Qt establishes the parent-child relationship at the beginning of clueDialog's lifetime.
I believe this will fix both your issues: 1) the clue window frame, caption, etc. will be painted, 2) you will be able to iterate for proper children of newEntry.

What's the purpose of the GtkWidget.events property for (like) GtkTreeView widgets?

I have a Glade GUI description file with a GtkTreeView in a GtkHBox in a window; and there's a handler for the row_activated signal. Now, Glade has automatically set the "events" property (inherited from GtkWidget) of that treeview to some value (GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK). And there are two strange things with this:
removing the pre-set value (so that the property is empty) doesn't seem to break the application (at least not with the old GTK 2.10 I have atm).
in fact, an annoying bug I has seen before (where the treeview items would not correctly react to expand or collapse clicks) is now gone!
I have yet to test this with a newer GTK version, but the question is already there: exactly what is the purpose for this events property? And why does Glade automatically and unnecessarily set it to some value? Does this have some side effects I'm not aware of?
It's a bug in glade, it always sets the event property of widgets it create. It has no notion of the default value of a property so it always sets it.
Doesn't this mask indicate the events you're willing to receive? In this case, you'll probably want to receive notification that the user has clicked or double-clicked an item in the GtkTreeView, and you'll want to register callbacks to handle these events.
me.yahoo.com/a/kUQ7zeQ: but even if I set the property to an empty string as mentioned, the row_activated handler is still called when I double-click on a row (or press Enter or Space). So the treeview still gets events...

Resources