Get the contents of a widget in a layout in PyQt - 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)

Related

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.

Kivy RecycleView: Get indices of all data items that are currently in view

I need to get the indices of all data items that are currently in view in a Kivy RecycleView widget. I want to display many Image widgets for which I render a texture and apply it to them. To save memory I need to delete these textures if they are not in view any more. I tried using the Kivy RecycleView example and modify it for my needs:
class SelectableImage(RecycleDataViewBehavior, Image):
def refresh_view_attrs(self, rv, index, data):
#Catch and handle the view changes
#print in view
print(index)
#call initial function of image class
return super(SelectableImage, self).refresh_view_attrs(rv, index, data)
The problem here is that refresh_view_attrs() only fires when a new Image widget gets added to the view. Thus I can only know what that last Image is, but not if there are any other in view. For this I'd also need to know which widget disappeared from the view. Is there any function in the RecycleView widget that I can use to obtain such information? Maybe there is a function that gets called whenever the view changes?
Okay, I found three possible solutions for my issue:
1. Solution
Calculate the position of all the Image widgets yourself and compare it with the position of the scrollbar to get the widgets that are currently displayed.
This is quite hacky and the RecycleView already does this internally. Thus I'd save the unnecessary computing and avoid this approach.
2. Solution
Use the get_visible_view(index) function of the view_adapter property of a RecycleView. This returns the currently visible view associated with index. If it return None, the view associated with index is not visible right now. This is how it's called for example:
self.myRecycleView.view_adapter.get_visible_view(index)
You could loop through the entire length of your data list and check for each item (the index in the list) if it is currently displayed or not.
3. Solution
My favourite approach: Use get_view_index_at(pos) of the layout_manager property to check what view index is at the given coordinates. This way you could check which item is at the top of the RecycleLayout widget and which one is at the bottom. You need to use coordinate transformation though. Example:
#get position at top center of RecycleView (upper limit)
pos = self.myRecycleView.to_local(self.myRecycleView.center_x, self.myRecycleView.height)
#check which items collides with the given position
print(self.myRecycleView.layout_manager.get_view_index_at(pos))
I hope this clears some things up!

PyQt check if value of qlabel changed

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)

How to create an custom View for ListView?

How to create an custom ListView? I have Adapter, but I don't understand how to create an View like ListView of the Facebook, or App for SMS native from device... I'm needing background for TextView, this background, will have an arrow pointing left or right, I tried to create a View using canvas, but it is very difficult...
Every line in the listView of a layout which can be as complex as you want.Just you need an extra xml file for managing you custom layout (it should be contains widgets,fields,images etc as your design ) and the adapter would inflate this layout file for each row in its getView () method and assign the data to the individual views in the row .

PyQt4: disable deleting widget after setCentralWidget

I have two custom widgets (two classes based on QtGui.QWidget). In __init__ of QtGui.QMainWindow I create their instances:
self.MyWidget1 = MyWidget1()
self.MyWidget2 = MyWidget2()
There are also two buttons (QtGui.QPushButton) in __init__ part, and there are two slots when user clicks each of them:
def clickButton1(self):
self.setCentralWidget(self.MyWidget1)
def clickButton2(self):
self.setCentralWidget(self.MyWidget2)
But it works only on first click and then PyQt says that underlying widget (MyWidget1 or MyWidget2) was deleted. I think it was done by sip module. Is there a way to prevent deleting widgets after reseting of central widget? Thanks!
I think it's almost impossible.
From setCentralWidget docs:
Note: QMainWindow takes ownership of the widget pointer and deletes it at the appropriate time.
So, you should create new MyWidget instance.
def clickButton2(self):
self.setCentralWidget(MyWidget2())
But the right way of doing such things is to use QStackedWidget

Resources