How do i found QPushButton in uic.load() *.ui file? - pyqt4

from images import mainwindow
from PyQt4.QtGui import QWidget, QMainWindow
class mainwindow_ui(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.ui = uic.loadUi('mainwindow.ui',self)
button = self.ui.exitBtn
self.ui.show()
How to interactive with button object on Python console?
Tab completion work.
After tab press, there is no mainwindow_ui.exitBtn - or mainwindow.button why?

uic.loadUi essentially loading the widget name into the classes namespace.
if you named the widget "foo" from within Qdesigner then you can access it via self.foo

Related

Proper way of managing multiple windows in PySide?

I have this app where I have several settings windows that open when buttons from the main window are clicked. The windows are application modal, so only one is open at a time. I have two ideas as to how to manage them, but I'm not sure which one would be the proper way to do it. I don't particularly care how the values are stored, as long as I can pass them to other windows in the app and do stuff with them.
MainWindow class Option 1:
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
central = QWidget()
layout = QVBoxLayout()
button = QPushButton('Show window')
layout.addWidget(button)
window = OtherWindow()
button.clicked.connect(window.show)
# I can pull the settings and pass them on to other windows if needed.
self.setCentralWidget(central)
MainWindow class Option 2:
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.other_settings = {}
button = QPushButton('Show window')
button.clicked.connect(self.show_other)
def show_other(self):
other_window = OtherWindow()
if other_window.exec():
self.other_settings.update(other_window.settings)
OtherWindow class:
class OtherWindow(QDialog):
def __init__(self):
super().__init__()
self.settings = {}
# widgets
box = QSpinBox(objectName='spinbox')
box.valueChanged.connect(self.save_settings)
# and so on ...
def save_settings(self):
sender = self.sender()
self.settings[sender.objectName()] = sender.value()
If i've understood your question correctly, look at this link which might be useful.
Small addition from me is, look here.
from PyQt5.QtWidgets import QDialog
from ui_imagedialog import Ui_ImageDialog
class ImageDialog(QDialog):
def __init__(self):
super(ImageDialog, self).__init__()
# Set up the user interface from Designer.
self.ui = Ui_ImageDialog()
self.ui.setupUi(self)
# Make some local modifications.
self.ui.colorDepthCombo.addItem("2 colors (1 bit per pixel)")
# Connect up the buttons.
self.ui.okButton.clicked.connect(self.accept)
self.ui.cancelButton.clicked.connect(self.reject)
Once you've got your .ui files it is a good practice to use (second link, second example - mentoned above) pyside6-uic or pyuic5 - depending of your needs.
Then you're creating class which role is to setup desired QWidget ui converted python module.
So in QtDesigner you're creating a QWidget:
screen_qt_designer
then do all your stuff, that it would like to do - place over QLineEdit, QPushButtons, etc., then save that file in your project's folder. After that all you have to do is use pyuic or pyside6-uic with proper settings (look at --help to set the output filename).
Then all you have is a .ui file (which is used in case you would like to add some widget, or change the widget all all) and your generated python class that inherits QObject, eg:
class Ui_Form(object):
def setupUi(self, Form):
if not Form.objectName():
Form.setObjectName(u"Form")
Form.resize(800, 600)
self.verticalLayout = QVBoxLayout(Form)
self.verticalLayout.setObjectName(u"verticalLayout")
self.label = QLabel(Form)
self.label.setObjectName(u"label")
Then create a another Python file, that inherits this generated class, eg.:
from PySide6.QtWidgets import QWidget
from CreateNewDatabase_ui import Ui_Form
class NewDatabaseWidget(QWidget):
def __init__(self):
super().__init__()
self.ui = Ui_Form()
self.ui.setupUi(self)
That's all. You have your prepared QWidget for adding it into a QStackedWidget. I use it in my own program and it fit me very well.
Edit:
I've forgot about 2 important notes:
Never ever edit your file generated by pyuic or pyside6-uic program. Whenever you wish to change the .ui file, all changes made to autogenerated code will be lost.
It's better to keep all signals/slots, logic mechanism in your QMainWindow class. It's better approach in case of code readability.

PySide2 change QLabel text by clicking QPushButton

I'm trying to change QLabel text by clicking QPushbutton.
I installed PySide2==5.15.2.1
Python 3.7.6 32bit in Windows 10 environment.
First, I made UI class (well, I didn't used Qt designer so I don't have *.ui file)
import PySide2.QtWidgets as qtw
...
class UI_MainWindow(object):
def setupUI(self, MainWindow):
window = qtw.QWidget()
someButton = qtw.QPushButton("button")
someLabel = qtw.QLabel("---")
...
MainWindow.setCentralWidget(window)
And there is some other class who has functions and connects as below
import PySide2.QtWidgets as qtw
from uiSomething import UI_MainWindow #uiSomething is a name of the file of the code above, who has UI_MainWindow class.
...
class something(qtw.QMainWindow, UI_MainWindow):
def __init__(self):
super(something, self).__init__()
self.ui = UI_MainWindow()
self.ui.setupUI(self)
self.someButton.clicked.connect(self.function) # not working. ui.someButton... also not working.
#if I put this connect in UI_MainWindow, at least connect works.
def function(self):
self.ui.someLabel.setText("change text") # not working. ui.someLabel...also not working.
and the other file, I put main function
import Something
import PySide2.QtWidgets as qtw
...
if __name__ == "__main__":
app = qtw.QApplication()
MainWindow = Something.something()
MainWindow.show()
app.exec__()
However, it just give me an error message as below when I click the button.
AttributeEror: 'UI_MainWindow' object has no attribute 'someLabel'
I thought it's okay to define every widgets in setupUI function but probably not..?
Please let me know if there is any idea.
Thank you in advance!
Best wishes,
JESuh
Because someButton and someLabel are not declared as class attributes. These variables are only accessible within the function(setupUI). Objects created from UI_MainWidow cannot call or modify them. Not even if you create a subclass of UI_MainWindow.
Change
import PySide2.QtWidgets as qtw
...
class UI_MainWindow(object):
def setupUI(self, MainWindow):
window = qtw.QWidget()
someButton = qtw.QPushButton("button")
someLabel = qtw.QLabel("---")
...
MainWindow.setCentralWidget(window)
To
import PySide2.QtWidgets as qtw
...
class UI_MainWindow(object):
def setupUI(self, MainWindow):
window = qtw.QWidget()
self.someButton = qtw.QPushButton("button")
self.someLabel = qtw.QLabel("---")
...
MainWindow.setCentralWidget(window)
#blaqICE's answer is a good start but I'm noticing a handful of other things that are contributing to your issues.
The main things I'm seeing are your use of class inheritance and instance attributes. Overall organization seems to be working against you as well. The way you're doing it is workable but it gets confusing pretty quickly. I'm not sure how familiar you are with creating classes but I would spend some time in the python classes docs and looking at PySide example code.
If you want to fix your code the way it is all you need to do is fix the lines I commented on:
uiSomething.py
import PySide2.QtWidgets as qtw
class UI_MainWindow(object):
def setupUI(self, MainWindow): # consider using __init__ instead
self.window = qtw.QWidget() # make an instance attribute for later access with your class instance; not needed with __init__ and proper inheritance
self.main_layout = qtw.QVBoxLayout() # create a layout to hold everything
self.window.setLayout(self.main_layout) # set 'self.window' layout to the new 'self.main_layout'
self.someButton = qtw.QPushButton("button") # make an instance attribute for later access with your class instance
self.main_layout.addWidget(self.someButton) # add 'self.someButton' to 'self.main_layout'
self.someLabel = qtw.QLabel("---") # make an instance attribute for later access with your class instance
self.main_layout.addWidget(self.someLabel) # add 'self.someLabel' to 'self.main_layout'
MainWindow.setCentralWidget(self.window)
Something.py
from uiSomething import UI_MainWindow
class something(qtw.QMainWindow, UI_MainWindow):
def __init__(self):
super(something, self).__init__()
self.ui = UI_MainWindow()
self.ui.setupUI(self) # consider using __init__ in class definition instead; this line would not be needed
self.ui.someButton.clicked.connect(self.function) # 'self.ui' before 'someButton' to access instance's someButton
def function(self):
self.ui.someLabel.setText("change text") # this is fine
# this was not working because of the issue with someButton's signal connection
main.py
import Something
import PySide2.QtWidgets as qtw
# import sys
if __name__ == "__main__":
app = qtw.QApplication()
MainWindow = Something.something()
MainWindow.show()
app.exec_() # only one underscore; typically done as 'sys.exit(app.exec_())' to formally exit python interpreter
However, a better implementation would be:
uiSomething.py
import PySide2.QtWidgets as qtw
class UI_MainWidget(qtw.QWidget): # UI_MainWindow -> UI_MainWidget for clarity; inherit QWidget
def __init__(self, button_text="button", lable_click_text="change text", parent=None): # auto initialize object
super(UI_MainWidget, self).__init__(parent) # pass parent to inherited class __init__ function
# 'self.window' no longer needed due to __init__ and can be accessed simply through 'self'
self.parent = parent # set parent as instance variable for later use if needed
self.button_text = button_text # set custom arguments as instance variable for later use if needed
self.lable_click_text = lable_click_text # set custom arguments as instance variable for later use if needed
self.main_layout = qtw.QVBoxLayout() # create a layout to hold everything
self.setLayout(self.main_layout) # set the widget's layout to the new self.main_layout
self.someButton = qtw.QPushButton(self.button_text) # class argument for easy customization of other instances
self.someButton.clicked.connect(self.function) # moved to instantiation class for clarity and ease of access
self.main_layout.addWidget(self.someButton)
self.someLabel = qtw.QLabel("---") # placeholder text
self.main_layout.addWidget(self.someLabel)
# moved '.setCentralWidget(self)' to main window class for organization and ease of access
def function(self): # move to instantiation class for clarity, organization, and ease of access
# 'self.ui' no longer needed in instantiation class, use 'self' instead
self.someLabel.setText(self.lable_click_text) # class argument for easy customization of other instances
Something.py
import PySide2.QtWidgets as qtw # need to import module here as well due to inheritance
from uiSomething import UI_MainWidget
# for this class, double inheritance doesn't really have any effect. Stick with the main one it represents.
class UI_MainWindow(qtw.QMainWindow): # something -> UI_MainWindow for clarity; inherit QMainWindow only; PEP 8 naming
def __init__(self, parent=None): # added parent kwarg for parenting to other widgets if needed
super(UI_MainWindow, self).__init__(parent) # pass parent to inherited class __init__ function
self.ui = UI_MainWidget(parent=self)
# self.ui.setupUI(self) # no longer needed due to __init__; can delete
# using custom class keyword arguments
# self.ui = UI_MainWidget(button_text="new button name", lable_click_text="new button clicked", parent=self)
# self.ui = UI_MainWidget(button_text="another button name", lable_click_text="another button clicked", parent=self)
self.setCentralWidget(self.ui)
main.py
import Something
import PySide2.QtWidgets as qtw
import sys
if __name__ == "__main__":
app = qtw.QApplication()
MainWindow = Something.UI_MainWindow()
MainWindow.show()
sys.exit(app.exec_())

Pyqt 5 how to make QLineEdit clickable

I just wonder how to make a QLineEdit clickable because I want when the QLineEdit is clicked to clear the line's text.
Here is my 2 cents...
Definition :
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtCore import pyqtSignal
class cQLineEdit(QLineEdit):
clicked= pyqtSignal()
def __init__(self,widget):
super().__init__(widget)
def mousePressEvent(self,QMouseEvent):
self.clicked.emit()
usage :
self.cLE = cQLineEdit(self)
self.cLE.setFixedWidth(20)
self.cLE.move(10,200)
self.cLE.clicked.connect(self.printText)
def printText(self):
print("Yop,+++")
Hope this can help.
Try Below Code to make QLineEdit clickable :
class ClickableLabel(QLabel):
clicked = pyqtSignal()
def __init__(self,name, widget):
super().__init__(name, widget)
def mousePressEvent(self, QMouseEvent):
self.clicked.emit()

how to approach a QSpinbox in other widgets?

I'm using Qt-desiger to make a GUI.
For example I have a QSpinbox in a QCombobox in a Groubbox.
How can i use SetValue for my Spinbox?
how i have to "describe" the way to my Spinbox?
Widgets inside other Widgets do not create hierarchy in Qt, it means that if you have widget1 inside widget2 you can directly access the widget1, like self.widget1 (and self.widget2)
You can create a class which will contain all your widgets on your ui form as follows:
from PyQt4 import uic
Form, Base = uic.loadUiType(r'path\to\your\uifile.ui') #get ui Form and Base class
class Window(Form, Base):
def __init__(self, parent = None):
#here you can access your widgets
#self.combobox.addItem('Item')
#self.spinbox.setValue(10)
...
That's all you need.
You first need to use pyuic to generate a python module from the designer ui file:
pyuic4 -o mainwindow_ui.py mainwindow.ui
Then import it into your application:
from PyQt4 import QtCore, QtGui
from mainwindow_ui import Ui_MainWindow
class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
This will add all the widgets from Qt Designer, and make them attributes of the MainWindow class. The attribute names will be the same as the objectName property that was set in Qt Designer. So if the QComboBox was named "comboBox", and the QSpinBox named "spinBox", they could be accessed within the MainWindow class like this:
self.comboBox.addItems('Foo')
self.spinBox.setValue(10)

QMainWindow flashes and disappears when called from another QMainWindow

This fairly minimal code creates a systray item with three right click options. One is an instance of QDialog, another QMainWindow, and also Quit. It's for a systray-driven app that will have some qdialogs and also a qmainwindow containing a table widget (or, is it possible to create a table into a qdialog?). I've been stuck on this for a week or so, read a lot of related materials and do not understand how to resolve it.
From the systray icon menu, clicking on QDialog, the dialog opens, waits for user action, and clicking the Ok or Cancel buttons will print which one was clicked. It would seem this works because QDialog has its own exec_(). Great so far.
However, clicking on the QMainWindow menu option, the main window dialog appears briefly and disappears with no chance for user input, of course. Maybe instead, the qmainwindow dialog would need to rely on the QApplication's exec_() where the object would instead be initialized just before app.exec_() perhaps? If that would work, I'm not clear on how def qmainwindow() would retrieve the information back from the user.
Hopefully a simple matter for someone who knows, a few changes, bingo.
Current environment: Windows 7 or XP, Python 2.7, Pyside
If you run this, there will be a blank place-holder in the systray that is clickable (right click), or you can also give it an actual image in place of 'sample.png'.
#!python
from PySide import QtGui, QtCore
from PySide.QtGui import QApplication, QDialog, QMainWindow
def qdialog():
qdialog_class_obj = TestClassQDialog()
qdialog_class_obj.show()
qdialog_class_obj.exec_() # wait for user
print "qdialog_user_action: ", qdialog_class_obj.qdialog_user_action
def qmainwindow():
qmainwindow_class_obj = TestClassQMainWindow()
qmainwindow_class_obj.show()
#qmainwindow_class_obj.exec_() # 'TestClassQMainWindow' object has no attribute 'exec_'
class TestClassQDialog(QDialog):
def __init__(self, parent=None):
super(TestClassQDialog, self).__init__(parent)
self.ok_cancel = QtGui.QDialogButtonBox(self)
self.ok_cancel.setStandardButtons(QtGui.QDialogButtonBox.Ok|QtGui.QDialogButtonBox.Cancel)
QtCore.QObject.connect(self.ok_cancel, QtCore.SIGNAL("accepted()"), self.button_ok)
QtCore.QObject.connect(self.ok_cancel, QtCore.SIGNAL("rejected()"), self.button_cancel)
def button_ok(self):
self.qdialog_user_action = 'ok'
self.hide()
def button_cancel(self):
self.qdialog_user_action = 'cancel'
self.hide()
class TestClassQMainWindow(QMainWindow):
def __init__(self, parent=None):
super(TestClassQMainWindow, self).__init__(parent)
self.ok_cancel = QtGui.QDialogButtonBox(self)
self.ok_cancel.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
QtCore.QObject.connect(self.ok_cancel, QtCore.SIGNAL("accepted()"), self.button_ok)
QtCore.QObject.connect(self.ok_cancel, QtCore.SIGNAL("rejected()"), self.button_cancel)
def button_ok(self):
self.hide()
def button_cancel(self):
self.hide()
class SysTrayIcon(QMainWindow):
def __init__(self, parent=None):
super(SysTrayIcon, self).__init__(parent)
self.qdialog_action = QtGui.QAction("QDialog", self, triggered=qdialog)
self.qmainwindow_action = QtGui.QAction("QMainWindow", self, triggered=qmainwindow)
self.quit_action = QtGui.QAction("Quit", self, triggered=QtGui.qApp.quit)
self.createSystrayIcon()
self.systrayIcon.show()
def createSystrayIcon(self):
self.systrayIconMenu = QtGui.QMenu(self)
self.systrayIconMenu.addAction(self.qdialog_action)
self.systrayIconMenu.addAction(self.qmainwindow_action)
self.systrayIconMenu.addSeparator()
self.systrayIconMenu.addAction(self.quit_action)
self.systrayIcon = QtGui.QSystemTrayIcon(self)
self.systrayIcon.setContextMenu(self.systrayIconMenu)
self.systrayIcon.setIcon(QtGui.QIcon('sample.png')) # point to a valid image if you want.
self.systrayIcon.setVisible(True)
if __name__ == '__main__':
app = QtGui.QApplication([])
systrayicon = SysTrayIcon()
app.exec_()
I've got it working. What I did was move your external method qmainwindow inside of your
SysTrayIcon and created the class parameter self.qmainwindow_class_obj = TestClassQMainWindow(). I've attached the working code below. Also, you're using the old style signal slot method, I take it you're coming from old school PyQt. The new method if very nice, clean and pythonic. I've also put the new style methods in the below code. Another thing I would do is move your qdialog method inside the SysTrayIcon class. I don't really understand why you have it outside the class but maybe I'm missing something. Hope this helps.
#!python
from PySide import QtGui, QtCore
from PySide.QtGui import QApplication, QDialog, QMainWindow
def qdialog():
qdialog_class_obj = TestClassQDialog()
qdialog_class_obj.show()
qdialog_class_obj.exec_() # wait for user
print "qdialog_user_action: ", qdialog_class_obj.qdialog_user_action
class TestClassQDialog(QDialog):
def __init__(self, parent=None):
super(TestClassQDialog, self).__init__(parent)
self.ok_cancel = QtGui.QDialogButtonBox(self)
self.ok_cancel.setStandardButtons(QtGui.QDialogButtonBox.Ok|QtGui.QDialogButtonBox.Cancel)
self.ok_cancel.accepted.connect(self.button_ok)
self.ok_cancel.rejected.connect(self.button_cancel)
def button_ok(self):
self.qdialog_user_action = 'ok'
self.hide()
def button_cancel(self):
self.qdialog_user_action = 'cancel'
self.hide()
class TestClassQMainWindow(QMainWindow):
def __init__(self, parent=None):
super(TestClassQMainWindow, self).__init__(parent)
self.ok_cancel = QtGui.QDialogButtonBox(self)
self.ok_cancel.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.ok_cancel.accepted.connect(self.button_ok)
self.ok_cancel.rejected.connect(self.button_cancel)
def button_ok(self):
self.hide()
def button_cancel(self):
self.hide()
class SysTrayIcon(QMainWindow):
def __init__(self, parent=None):
super(SysTrayIcon, self).__init__(parent)
self.qmainwindow_class_obj = TestClassQMainWindow()
self.qdialog_action = QtGui.QAction("QDialog", self, triggered=qdialog)
self.qmainwindow_action = QtGui.QAction("QMainWindow", self, triggered=self.qmainwindow)
self.quit_action = QtGui.QAction("Quit", self, triggered=QtGui.qApp.quit)
self.createSystrayIcon()
self.systrayIcon.show()
def createSystrayIcon(self):
self.systrayIconMenu = QtGui.QMenu(self)
self.systrayIconMenu.addAction(self.qdialog_action)
self.systrayIconMenu.addAction(self.qmainwindow_action)
self.systrayIconMenu.addSeparator()
self.systrayIconMenu.addAction(self.quit_action)
self.systrayIcon = QtGui.QSystemTrayIcon(self)
self.systrayIcon.setContextMenu(self.systrayIconMenu)
self.systrayIcon.setIcon(QtGui.QIcon('linux.jpeg')) # point to a valid image if you want.
self.systrayIcon.setVisible(True)
def qmainwindow(self):
self.qmainwindow_class_obj.show()
if __name__ == '__main__':
app = QtGui.QApplication([])
systrayicon = SysTrayIcon()
app.exec_()

Resources