Using a checkbox in pyqt - python

1) I have a checkbox called "ch_check" in my UI created with Qt designer that needs to be tested
2) There is also a button, "bt_button", which triggers a simple function:
self.dlg.bt_button.clicked.connect(self.doCheck)
3) The function:
def doCheck(self):
if ch_check.isChecked():
self.dlg.le_text.setText("Hello")
else:
self.dlg.le_text.setText("Nope")
However I can't figure out how to reference the box properly. How would I do that? Do I need to connect the checkbox somehow first? All the examples I found so far use checkboxes to fire off functions and whatnot while completely ignoring this basic usage. I found this question but it's not answering how to address the existing checkbox: How to check if a checkbox is checked in pyqt

You can do this utilizing the StateChanged signal. For this example we have a simple .ui and a simple .py file:
The .ui file defines two widgets. A check box (ch_check) and a single QLabel (my_label)
The python file:
from PyQt4 import QtCore
from PyQt4 import QtGui
import sys
from test_ui import Ui_MainWindow
class CheckDialog(QtGui.QMainWindow):
def __init__(self):
QtGui.QWidget.__init__(self)
# Set up the user interface from Designer.
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.ch_check.stateChanged.connect(self.state_changed)
def state_changed(self, int):
if self.ui.ch_check.isChecked():
self.ui.my_label.setText("CHECKED!")
else:
self.ui.my_label.setText("UNCHECKED!")
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = CheckDialog()
window.show()
sys.exit(app.exec_())
Explanation:
We set up our signal with this line:
self.ui.ch_check.stateChanged.connect(self.state_changed)
When the state of the checkbox changes, it will call the state_changed function. This is where your logic to check whether the box is checked or unchecked goes.
def state_changed(self, int):
if self.ui.ch_check.isChecked():
self.ui.my_label.setText("CHECKED!")
else:
self.ui.my_label.setText("UNCHECKED!")
In the function, we determine if the check box has been checked. If so, we change our label to say "CHECKED", if it is unchecked the label changes to "UNCHECKED".
Example:
When the application is launched the UI looks like this:
Checking the box, changes the label:
Unchecking the box, also changes the label:

As mentioned in the comment above, I just made a small mistake. The correct code would be:
def doCheck(self):
checker = self.dlg.ch_check
if self.dlg.ch_check.isChecked():
self.dlg.le_text.setText("Hello")
else:
self.dlg.le_text.setText("Nope")

Related

How PySide6 paintEvent function for a PushButton works?

A long time ago, I wanted to make a logo appear on top of the text in a QPushButton stacked on top of each other, but I couldn't find anyway
I read some stylesheets (couldn't find a single doc to read it all about all styles I can apply to a button)
tried the setLayoutDirection (RightToLeft and LeftToRight were there, but no UpToDown direction)
In my (I wish) last attempt I tried to inherit a QAbstractButton (I didn't find QAbstractPushButton, so I guess QAbstractButton is the answer) and change its paintEvent/paintEngine to draw an image or maybe add a vbox inside it as a layout to draw to components, but I can't find anything in python (specially PySide) which has an example in any possible way close to that. The best thing I found was the analogue clock example which was not very helpful because it was trying to work a QWidget and not a QAbstractButton and I want to keep the feel of a Native looking button.
I like my final product to be something like this.
source of the implemention of that
Python Enaml toolkit supported this feature out of the box (in one of its widgets), and I know it is QT based, so I really wish to know how it is possible?
p.s.: Also, is there a market for qt widgets? e.g.: a plugin system. Because rewriting an android like switch doesn't seem like the correct thing that I should do! even a good tutorial or doc would be appreicated (excluding official doc)
It is easier than you think, you can use QToolButton() like this:
import sys
from PySide6.QtCore import Qt, QSize
from PySide6.QtWidgets import QApplication, QVBoxLayout,QStyle, QWidget,
QToolButton
class Window(QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
button = QToolButton()
# here you choose the position of the icon and its text
button.setToolButtonStyle(
Qt.ToolButtonStyle.ToolButtonTextUnderIcon)
# here I just use built-in icon by PySide6 for this example
name = 'SP_DialogSaveButton'
pixmapi = getattr(QStyle, name)
icon = self.style().standardIcon(pixmapi)
# here we set text and icon of size 32x32 to the button
button.setIcon(icon)
button.setText("Sample text")
button.setIconSize(QSize(32, 32))
# finally we add our button to the layout
lay = QVBoxLayout(self)
lay.addWidget(button, alignment=Qt.AlignCenter)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec())

PyQT5 Designer add checkbox i Python when I have separate file for code

My problem is that I have a file with my UI called xxx.ui. Then as many have suggested I created another python file called test.py where I have put code to use my xxx.ui:
# imports
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import uic
import sys
class Ui(QtWidgets.QMainWindow):
def __init__(self):
super(Ui, self).__init__()
uic.loadUi('xxx.ui', self)
self.show()
app = QtWidgets.QApplication(sys.argv)
window = Ui()
app.exec_()
Up until this stage everything works ok. But now I would like to add a checkbox to my UI whe program starts without messing inside xxx.ui (so the checkbox will be created dynamicaly when the program runs).
How can I do that ???
Thank You in advance.
After many fail attempts I have found how to do it:
To add Checkbox outside of xxx.ui file. I went to my test.py file and added code below this line:
uic.loadUi('xxx.ui', self)
The code looks like that (I am using horizontal layout widget created in designer called seasonLayout and my checkbox is inside that layout):
self.checkBox = QtWidgets.QCheckBox(self.horizontalLayoutWidget)
self.checkBox.setObjectName("checkBox_0")
self.checkBox.setText('Hello')
self.seasonLayout.addWidget(self.checkBox)
Then if You want to get to that object all You have to do is to use code below:
(here i change text of this newly created checkbox):
self.checkBoxs = self.findChild(QtWidgets.QCheckBox, 'checkBox_0')
self.checkBoxs.setText('test')
Hopefuly it will be helpful for other because I have really tried to find answer for that almost everywhere and everyone were just using widgets from designer - noone explain how to add them outside of it.

pyqt5 - connect a function when QComboBox is clicked [duplicate]

I have been trying to get a QComboBox in PyQt5 to become populated from a database table. The problem is trying to find a method that recognizes a click event on it.
In my GUI, my combo-box is initially empty, but upon clicking on it I wish for the click event to activate my method for communicating to the database and populating the drop-down list. It seems so far that there is no built-in event handler for a click-event for the combo-box. I am hoping that I am wrong on this. I hope someone will be able to tell me that there is a way to do this.
The best article I could find on my use-case here is from this link referring to PyQt4 QComboBox:
dropdown event/callback in combo-box in pyqt4
I also found another link that contains a nice image of a QComboBox.
The first element seems to be a label followed by a list:
Catch mouse button pressed signal from QComboBox popup menu
You can override the showPopup method to achieve this, which will work no matter how the drop-down list is opened (i.e. via the mouse, keyboard, or shortcuts):
from PyQt5 import QtCore, QtWidgets
class ComboBox(QtWidgets.QComboBox):
popupAboutToBeShown = QtCore.pyqtSignal()
def showPopup(self):
self.popupAboutToBeShown.emit()
super(ComboBox, self).showPopup()
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.combo = ComboBox(self)
self.combo.popupAboutToBeShown.connect(self.populateConbo)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.combo)
def populateConbo(self):
if not self.combo.count():
self.combo.addItems('One Two Three Four'.split())
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
However, for your particular use-case, I think a better solution might be to set a QSqlQueryModel on the combo-box, so that the items are updated from the database automatically.
Alternative Solution I :
We can use frame click, the code is to be used in the container of the combo box (windows/dialog/etc.)
def mousePressEvent(self, event):
print("Hello world !")
or
def mousePressEvent():
print("Hello world !")
Alternative Solution II :
We could connect a handler to the pressed signal of the combo's view
self.uiComboBox.view().pressed.connect(self.handleItemPressed)
...
def handleItemPressed(self, index):
item = self.uiComboBox.model().itemFromIndex(index)
print("Do something with the selected item")
Why would you want to populate it when it's activated rather than when the window is loaded?
I am currently developing an application with PySide (another Python binding for the Qt framework), and I populate my comboboxes in the mainwindow class __init__ function, which seems to be the way to go, judging by many examples.
Look at the example code under "QCombobox" over at Zetcode.

signal clicked works only with static methods

I'm using PyQt5, I'm trying to create an application that involves a QPushButton. Now, when the user clicks this button, a function is supposed to be executed.
When I try to use button.clicked.connect(self.button_clicked_slot) it works as expected only and only if button_clicked_slot() is a static method, i.e. doesn't take self as an argument. In case it is a non-static method, the function isn't executed when the button is clicked.
I've tried various similar answers from StackOver and elsewhere, none of them could solve the problem I'm facing. I'm creating and using this button inside a class, the slot function is a method of this same class. I've tried to make the class inherit from QWidget and QObject, neither of those solutions worked. It always seems to boil down to using a staticmethod.
The entire code would be very big, however, here is an over-simplified code snippet with the exact same
import sys
from PyQt5 import QtWidgets, QtCore
class activity(QtWidgets.QWidget):
def __init__(self):
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QMainWindow()
button = QtWidgets.QPushButton('test button')
button.clicked.connect(self.temp_print)
window.setCentralWidget(button)
window.show()
sys.exit(app.exec_())
#staticmethod
def temp_print():
print('Reached here')
activity()
In the above code, the method temp_print() is executed whenever the button is clicked (because it is a staticmethod). However, if I rewrite the function as:
def temp_print(self):
print('Reached here')
And suddenly, this function is never executed regardless of how many times I click the button.
In several other code snippets and the official documentation, I've seen a non-static function being used as a slot and things seem to be going smoothly for them. The code snippet I shared above is an overly-simplified version of the problem that I'm facing.
And yes, in the code that I shared above, I don't need the self parameter inside the function and thus should be able to use a static method too. However, like I mentioned, this is a simplified version of the code I'm using (my actual code is over 500+ lines and thus it would be very stupid to paste the whole thing here), but, in my actual code, I am using the self parameter and thus need a non-static function to be used as the slot for click events.
Static methods can be invoked without the need to have an instance unlike the methods of the class that need the object to be created.
In your example, app.exec_() prevents the constructor from running, so the other methods of the class such as temp_print can not be called.
So there are 2 possible solutions:
Use a lambda method to invoke temp_print:
import sys
from PyQt5 import QtWidgets
class Activity:
def __init__(self):
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QMainWindow()
button = QtWidgets.QPushButton("test button")
button.clicked.connect(lambda: self.temp_print())
window.setCentralWidget(button)
window.show()
sys.exit(app.exec_())
def temp_print(self):
print("Reached here")
if __name__ == "__main__":
Activity()
Let the object finish building:
import sys
from PyQt5 import QtWidgets
class Activity:
def __init__(self):
self.m_app = QtWidgets.QApplication(sys.argv)
self.window = QtWidgets.QMainWindow()
button = QtWidgets.QPushButton("test button")
button.clicked.connect(self.temp_print)
self.window.setCentralWidget(button)
self.window.show()
def temp_print(self):
print("Reached here")
def run(self):
return self.m_app.exec_()
if __name__ == "__main__":
a = Activity()
sys.exit(a.run())

how to add an action to QtCore.Qt.DefaultContextMenu on Qdoublespinbox on right cilck?

I have developed a fairly complex GUI tool using the Qt Designer.
For more details about the tool see: https://github.com/3fon3fonov/trifon
I have defined many QDoubleSpinBox entries and by default the Qt Designer sets their right-click menu policy to:
setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
Now I want to add few more actions to this menu, but I simply cannot understand how this works! There is nothing in the Qt Designer which will allow me to make a "CustomContextMenu". I understand that for this I may need some coding (with which I will need help, and thus I am asking for help here), but I also need to make it globally for all SpinBox-es.
Sorry for not posting the code since it is fairly large for this form. If interested, please look at the github under "gui.py". However, there and in the .ui file there is no sign of any possibility to control the contextmenu policy for these buttons.
Instead I am posting an image of the tool (sorry for the bad image but PrtSc does not seem to work when the right button in clicked and the menu is displayed)
see GUI image here
As we want to add a QAction to the default context menu we first overwrite the contextMenuEvent event and use a QTimer to call a function that filters the toplevels and get the QMenu that is displayed and there we add the QAction:
doublespinbox.py
from PyQt5 import QtCore, QtWidgets
class DoubleSpinBox(QtWidgets.QDoubleSpinBox):
minimize_signal = QtCore.pyqtSignal()
def __init__(self, *args, **kwargs):
super(DoubleSpinBox, self).__init__(*args, **kwargs)
self.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
def contextMenuEvent(self, event):
QtCore.QTimer.singleShot(0, self.add_actions)
super(DoubleSpinBox, self).contextMenuEvent(event)
#QtCore.pyqtSlot()
def add_actions(self):
for w in QtWidgets.QApplication.topLevelWidgets():
if isinstance(w, QtWidgets.QMenu) and w.objectName() == "qt_edit_menu":
w.addSeparator()
minimize_action = w.addAction("minimize this parameter")
minimize_action.triggered.connect(self.minimize_signal)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = DoubleSpinBox()
w.show()
sys.exit(app.exec_())
To use DoubleSpinBox in Qt Designer, first place doublespinbox.py next to your .ui:
├── ..
├── rvmod_gui.ui
├── doublespinbox.py  
├── ...
then you must promote the widget to do so right click on the QDoubleSpinBox and select the option "Promote to ..." by adding the following to the dialog:
Then click on the Add button and then the Promote button.
For the other QDoubleSpinBox, right click and select the new Promote To option where the DoubleSpinBox option is.
You can find an example here

Categories