how to approach a QSpinbox in other widgets? - pyqt

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)

Related

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_())

How to translate ui file + several questions [duplicate]

I am trying to translate my small application written in pyside2/pyqt5 to several languages, for example, Chinese. After googling, I managed to change the main window to Chinese after select from the menu -> language -> Chinese. However, the pop up dialog from menu -> option still remains English version. It seems the translation info is not transferred to the dialog. How do I solve this?
Basically, I build two ui files in designer and convert to two python files:One mainui.py and one dialogui.py. I then convert the two python file into one *.ts file using
pylupdate5 -verbose mainui.py dialogui.py -ts zh_CN.ts
after that, in linguist input the translation words. I can see the items in the dialog, which means this information is not missing. Then I release the file as zh_CN.qm file. All this supporting file I attached below using google drive.
Supporting files for the question
The main file is as
import os
import sys
from PySide2 import QtCore, QtGui, QtWidgets
from mainui import Ui_MainWindow
from dialogui import Ui_Dialog
class OptionsDialog(QtWidgets.QDialog,Ui_Dialog):
def __init__(self,parent):
super().__init__(parent)
self.setupUi(self)
self.retranslateUi(self)
class MainWindow(QtWidgets.QMainWindow,Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.actionConfigure.triggered.connect(self.showdialog)
self.actionChinese.triggered.connect(self.change_lang)
def showdialog(self):
dlg = OptionsDialog(self)
dlg.exec_()
def change_lang(self):
trans = QtCore.QTranslator()
trans.load('zh_CN')
QtCore.QCoreApplication.instance().installTranslator(trans)
self.retranslateUi(self)
if __name__=='__main__':
app = QtWidgets.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
ret = app.exec_()
sys.exit(ret)
I think it should be a typical task because almost no application will only have a mainwindow.
You have to overwrite the changeEvent() method and call retranslateUi() when the event is of type QEvent::LanguageChange, on the other hand the QTranslator object must be a member of the class but it will be deleted and it will not exist when the changeEvent() method is called.
Finally assuming that the Language menu is used to establish only translations, a possible option is to establish the name of the .qm as data of the QActions and to use the triggered method of the QMenu as I show below:
from PySide2 import QtCore, QtGui, QtWidgets
from mainui import Ui_MainWindow
from dialogui import Ui_Dialog
class OptionsDialog(QtWidgets.QDialog,Ui_Dialog):
def __init__(self,parent):
super().__init__(parent)
self.setupUi(self)
def changeEvent(self, event):
if event.type() == QtCore.QEvent.LanguageChange:
self.retranslateUi(self)
super(OptionsDialog, self).changeEvent(event)
class MainWindow(QtWidgets.QMainWindow,Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.m_translator = QtCore.QTranslator(self)
self.actionConfigure.triggered.connect(self.showdialog)
self.menuLanguage.triggered.connect(self.change_lang)
# set translation for each submenu
self.actionChinese.setData('zh_CN')
#QtCore.Slot()
def showdialog(self):
dlg = OptionsDialog(self)
dlg.exec_()
#QtCore.Slot(QtWidgets.QAction)
def change_lang(self, action):
QtCore.QCoreApplication.instance().removeTranslator(self.m_translator)
if self.m_translator.load(action.data()):
QtCore.QCoreApplication.instance().installTranslator(self.m_translator)
def changeEvent(self, event):
if event.type() == QtCore.QEvent.LanguageChange:
self.retranslateUi(self)
super(MainWindow, self).changeEvent(event)
if __name__=='__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
ret = app.exec_()
sys.exit(ret)

Start the script in PyQt5 and python3 [duplicate]

I have created a form using PyQt4 which has a push button. On this push button I want to call another python script which looks like this:
File1.py:
import sys
from PyQt4 import QtCore, QtGui
from file1_ui import Ui_Form
class MyForm(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
File1_ui.py
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(400, 300)
self.pushButton = QtGui.QPushButton(Form)
self.pushButton.setGeometry(QtCore.QRect(120, 200, 95, 20))
self.pushButton.setObjectName(_fromUtf8("pushButton"))
self.retranslateUi(Form)
QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL(_fromUtf8("clicked()")), Form.close)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton.setText(QtGui.QApplication.translate("Form", "Close", None, QtGui.QApplication.UnicodeUTF8))
File2.py
import sys
from PyQt4 import Qt
from taurus.qt.qtgui.application import TaurusApplication
app = TaurusApplication(sys.argv)
panel = Qt.QWidget()
layout = Qt.QHBoxLayout()
panel.setLayout(layout)
from taurus.qt.qtgui.panel import TaurusForm
panel = TaurusForm()
model = [ 'test/i1/1/%s' % p for p in props ]
panel.setModel(model)
panel.show()
sys.exit(app.exec_())
File1_ui.py is created from the Qtdesigner and then I am using File1.py to execute it.So File2.py when executed alone opens up a panel and displays few attributes.I want this script to be called on the button click in the first form(file1.py) which I created using Qtdesigner.Could you let me know how I could achieve this functionality.Thanks.
You will need to make some modifications to File2.py to make the appropriate calls depending on whether it is running standalone or not. When you are launching the script via File1.py there will already be a QApplication instance with event loop running, so trying to create another and run its event loop will cause problems.
Firstly, move the core part of your script into its own function. This will allow you to easily call it from File1.py. You can then handle the case where the script is running standalone and needs to create a QApplication instance and start its event loop. (I am not familiar the the taurus library you are using, but you can probably substitute TaurusApplication for QtGui.QApplication)
File2.py:
import sys
from PyQt4 import QtCore, QtGui
def runscript():
panel = QtGui.QWidget()
layout = QtGui.QHBoxLayout(panel)
return panel # Must return reference or panel will be deleted upon return
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
panel = runscript()
panel.show()
sys.exit(app.exec_())
Assuming your files are in the same directory you can simply write import File2 and use File2.runscript() to run your code. You then just need to connect the function to your pushbuttons clicked() signal to run it. The only problem here is that the reference to the QWidget returned from the runscript() function will be lost (and the object deleted) if you connect directly to runscript(). For this reason I created a method launch_script() which saves a reference in MyForm.
File1.py:
import sys
from PyQt4 import QtCore, QtGui
from file1_ui import Ui_Form
import File2
class MyForm(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
# This is a bit of a hack.
self.ui.pushButton.clicked.connect(self.launch_script)
def launch_script(self):
self.panel = File2.runscript()
self.panel.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
I don't use Qt Designer, so I don't know the correct way to go about connecting the signal to launch_script(). The code I have written should work, but obviously violates OOP principles and is dependent on the name of the pushbutton widget assigned by the software.

add pyqtgraph (plot) into QApplication

hy,
soooo, i created the MainWindow.ui file with the QTDesigner. Then i import this gui with following command into my .py file:
form_class = uic.loadUiType("ess_project.ui")[0]
What is the difference if i compile this .ui file with pyuic4 ?
(every time i compiled my .ui file i got following error:
RuntimeError: the sip module implements API v11.0 to v11.1 but the PyQt4.QtCore module requires API v10.1
The MainWindow create the first window, where all buttons etc. are placed.
class MainWindow(QtGui.QMainWindow, form_class):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
PlotWindow.__init__(self)
self.setupUi(self)
self.pb_send.clicked.connect(self.pb_send_clicked)
self.pb_open.clicked.connect(self.pb_open_clicked)
self.pb_exit.clicked.connect(self.pb_exit_clicked)
self.comboBox.currentIndexChanged.connect(self.combo_box_changed)
furthermore i have a second class named "PlotWindow". This class looks like this:
class PlotWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.w = QtGui.QMainWindow()
self.cw = pg.GraphicsLayoutWidget()
self.w.show()
self.w.resize(900,600)
self.w.setCentralWidget(self.cw)
self.w.setWindowTitle('pyqtgraph: G-CODE')
self.p = self.cw.addPlot(row=0, col=0)
now as you can see, the PloWindow - class create a second Window.
How can i implement the pg.GraphicsLayoutWidget() into the MainWindow - class ??
not sure if this can help you ?!? :
def main():
app = QtGui.QApplication([])
myWindow = MainWindow(None)
myWindow.show()
app.exec_()
if __name__ == '__main__':
main()
I am using python3 !!!
feel FREE to comment :)
thanks !
To place any pyqtgraph widgets inside your application, you add a placeholder widget and "promote" it to the pg class that you want. See: http://www.pyqtgraph.org/documentation/how_to_use.html#embedding-widgets-inside-pyqt-applications

PyQt and QtDesigner

I am trying to implement a LED in PyQt named disLDR1 by trying to change the background color. I am trying to use QPalette to change the BackgroundRole. But what is the equivalent of Qt::red?
Is this the correct way to set the background color or is there any other way?
#!/usr/bin/python -d
import sys
from PyQt4 import QtCore, QtGui
from main import Ui_Form
from PyQt4.QtGui import QPalette
class Top(QtGui.QMainWindow):
def __init__(self, parent = None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
for i in 1, 10:
self.setOff()
self.setOn()
def setOff(self):
self.pal = QPalette(self.ui.disLDR1.palette())
self.pal.setColor(self.ui.disLDR1.backgroundRole(), <<<RED COLOR>>>)
self.ui.disLDR1.setPalette(pal)
def setOn(self):
self.pal = QPalette(self.ui.disLDR1.palette())
self.pal.setColor(self.ui.disLDR1.backgroundRole(), <<<GREEN COLOR>>>)
self.ui.disLDR1.setPalette(pal)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = Top()
myapp.show()
sys.exit(app.exec_())
EDIT: I have been trying to take help from In Qt, how do I set the background color of a widget like combobox or double spin box? but don't know what to substitute for QT::red
You can find the list of predefined Qt color objects at this link. In this case you would just need to use QtCore.Qt.red and QtCore.Qt.blue. You could also use the QColor class to generate arbitrary colors.
It's a matter of preference, but I personally think the easiest and most powerful way to go would be to use a style sheet.

Resources