Difference between revisions of "PyQt5 Simple Example"
(→Running the App) |
|||
(5 intermediate revisions by the same user not shown) | |||
Line 264: | Line 264: | ||
pyuic5 -x mainwindow.ui -o mainwindow.py | pyuic5 -x mainwindow.ui -o mainwindow.py | ||
− | : the '''-x''' option creates a main section to the '''mainwindow.py''' file that will allow us to test quickly whether the GUI looks as we intended. | + | : the '''-x''' option creates a main section to the '''mainwindow.py''' file that will allow us to test quickly whether the GUI looks as we intended. |
− | |||
− | |||
− | |||
− | |||
<br /> | <br /> | ||
==Edit the mainwindow.py File== | ==Edit the mainwindow.py File== | ||
Line 274: | Line 270: | ||
There are few edits you need to make to the mainwindow.py file. They are highlighted in yellowin the listing below. | There are few edits you need to make to the mainwindow.py file. They are highlighted in yellowin the listing below. | ||
<br /> | <br /> | ||
− | ::<source lang="python" highlight=" | + | ::<source lang="python" highlight="14,16,95,114,115,116"> |
# -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||
− | + | # mainwindow.py | |
+ | # generated by | ||
+ | # | ||
+ | # pyuic5 -x mainwindow.ui -o mainwindow.py | ||
+ | # | ||
# Form implementation generated from reading ui file 'mainwindow.ui' | # Form implementation generated from reading ui file 'mainwindow.ui' | ||
# | # | ||
Line 416: | Line 416: | ||
The '''addRandomTextSlot( self )''' addition is the slot we attached to the '''Random Text''' push-button in the GUI, using Designer. The '''pyuic5''' utility does not seem to generate code for it, and it's left up to us to do. | The '''addRandomTextSlot( self )''' addition is the slot we attached to the '''Random Text''' push-button in the GUI, using Designer. The '''pyuic5''' utility does not seem to generate code for it, and it's left up to us to do. | ||
<br /> | <br /> | ||
− | + | Try running the newly created file with Python 3: | |
+ | |||
+ | python3 mainwindow.py | ||
+ | |||
+ | You should see the GUI as illustrated above. Flip between the two tabs to verify that both have been populated. | ||
+ | <br /> | ||
+ | <br /> | ||
==Create the Main Application== | ==Create the Main Application== | ||
<br /> | <br /> | ||
Line 467: | Line 473: | ||
=Deploying= | =Deploying= | ||
<br /> | <br /> | ||
− | Deploying the newly created project can be done with [https://www.riverbankcomputing.com/software/pyqtdeploy/intro pyqtdeploy]. | + | Deploying the newly created project can be done with <!-- [https://www.riverbankcomputing.com/software/pyqtdeploy/intro pyqtdeploy], or --> [http://www.pyinstaller.org/ PyInstaller]. |
<br /> | <br /> | ||
<br /> | <br /> | ||
Line 482: | Line 488: | ||
<br /> | <br /> | ||
<br /> | <br /> | ||
− | [[Category:PyQt5]][[Category:Python]][[Category:Qt5]] | + | [[Category:PyQt5]][[Category:Python]][[Category:Qt5]][[Category:C++]] |
<br /> | <br /> |
Latest revision as of 10:18, 24 June 2018
D. Thiebaut (talk) 11:46, 13 June 2018 (EDT)
In this tutorial we create a GUI with Qt5's designer, take the ui file resulting from it, convert it to a py file with the pyuic5 utility, and add a custom slot associated with the clicked signal of one of the push-buttons.
Contents
Environment
- Mac OSX Sierra
- Qt5.10.1, with Qt Creator 4.6.2 (Clang 8.0 (Apple), 64 bits)
- Python 3.5
The GUI
We assume that you are familiar with creating a Qt5 GUI with Designer. If not, check out this tutorial which will take you through the required steps. The tutorial assumes Qt4, but should translate easily to Qt5.
Generating the GUI
- Open Qt5
- Create a New Project
- Pick Qt for the type of project
- Pick Qt Designer Form
- Pick Main Window as a template
- Accept mainwindow.ui as the name of the file
- Click Done
- Follow steps similar to those illustrated in this tutorial to create a main window with 2 tabs.
- First tab: label, line edit, push-button labeled Clear
- Second tab: textEdit, two push-buttons, labeled "Clear" and "Random Text"
- Edit signals and slots to create these connections
- On Tab 1, connect "clicked" signal of Clear push-button to clear() method of LineEdit widget
- On Tab 2, connect "clicked" signal of Clear push-button to clear() method of TextEdit widget
- ON Tab 2, connect "clicked" signal of Random Text push-button to a new slot called addRandomTextSlot() belonging to the main window.
The GUI with the two tabs
The Main Window GUI is shown below. It contains a TAB widget with two tabs, both shown.
The UI File
Once the GUI is created in Designer, save it to mainwindow.ui, shown below for reference.
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>482</width> <height>600</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralwidget"> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> <widget class="QTabWidget" name="tabWidget"> <property name="currentIndex"> <number>1</number> </property> <widget class="QWidget" name="tab"> <attribute name="title"> <string>Processor</string> </attribute> <layout class="QGridLayout" name="gridLayout_2"> <item row="0" column="0"> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QPushButton" name="clearButton"> <property name="text"> <string>Clear</string> </property> </widget> </item> <item> <widget class="QLineEdit" name="EAXlineEdit"/> </item> <item> <widget class="QLabel" name="label"> <property name="text"> <string>EAX</string> </property> </widget> </item> <item> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> </layout> </item> </layout> </widget> <widget class="QWidget" name="tab_2"> <attribute name="title"> <string>Memory</string> </attribute> <layout class="QGridLayout" name="gridLayout_4"> <item row="0" column="0"> <widget class="QTextEdit" name="textEdit"/> </item> <item row="1" column="0"> <layout class="QGridLayout" name="gridLayout_3"> <item row="0" column="0"> <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> <widget class="QPushButton" name="pushButton"> <property name="text"> <string>Clear</string> </property> </widget> </item> <item> <spacer name="horizontalSpacer_2"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item> <widget class="QPushButton" name="pushButton_2"> <property name="text"> <string>Random Text</string> </property> </widget> </item> </layout> </item> </layout> </item> </layout> </widget> </widget> </item> </layout> </widget> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>482</width> <height>22</height> </rect> </property> <widget class="QMenu" name="menuFile"> <property name="title"> <string>File</string> </property> <addaction name="actionSave_Program"/> <addaction name="actionLoad_Program"/> </widget> <widget class="QMenu" name="menuQuit"> <property name="title"> <string>Quit</string> </property> </widget> <widget class="QMenu" name="menuHelp"> <property name="title"> <string>Help</string> </property> </widget> <addaction name="menuFile"/> <addaction name="menuQuit"/> <addaction name="menuHelp"/> </widget> <widget class="QStatusBar" name="statusbar"/> <action name="actionSave_Program"> <property name="text"> <string>Save Program</string> </property> </action> <action name="actionLoad_Program"> <property name="text"> <string>Load Program</string> </property> </action> </widget> <resources/> <connections> <connection> <sender>clearButton</sender> <signal>clicked()</signal> <receiver>EAXlineEdit</receiver> <slot>clear()</slot> <hints> <hint type="sourcelabel"> <x>71</x> <y>301</y> </hint> <hint type="destinationlabel"> <x>192</x> <y>299</y> </hint> </hints> </connection> <connection> <sender>pushButton_2</sender> <signal>clicked()</signal> <receiver>MainWindow</receiver> <slot>addRandomTextSlot()</slot> <hints> <hint type="sourcelabel"> <x>363</x> <y>521</y> </hint> <hint type="destinationlabel"> <x>476</x> <y>440</y> </hint> </hints> </connection> <connection> <sender>pushButton</sender> <signal>clicked()</signal> <receiver>textEdit</receiver> <slot>clear()</slot> <hints> <hint type="sourcelabel"> <x>78</x> <y>521</y> </hint> <hint type="destinationlabel"> <x>92</x> <y>449</y> </hint> </hints> </connection> </connections> <slots> <slot>addRandomTextSlot()</slot> </slots> </ui>
PyQt5
Generating the Python version of the UI file
- Convert the .ui file to a Python .py file. Open a Terminal window and type the following command:
pyuic5 -x mainwindow.ui -o mainwindow.py
- the -x option creates a main section to the mainwindow.py file that will allow us to test quickly whether the GUI looks as we intended.
Edit the mainwindow.py File
There are few edits you need to make to the mainwindow.py file. They are highlighted in yellowin the listing below.
# -*- coding: utf-8 -*- # mainwindow.py # generated by # # pyuic5 -x mainwindow.ui -o mainwindow.py # # Form implementation generated from reading ui file 'mainwindow.ui' # # Created by: PyQt5 UI code generator 5.10.1 # # WARNING! All changes made in this file will be lost! from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import QObject, pyqtSlot class Ui_MainWindow( QObject): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(482, 600) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) self.tabWidget.setObjectName("tabWidget") self.tab = QtWidgets.QWidget() self.tab.setObjectName("tab") self.gridLayout_2 = QtWidgets.QGridLayout(self.tab) self.gridLayout_2.setObjectName("gridLayout_2") self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.clearButton = QtWidgets.QPushButton(self.tab) self.clearButton.setObjectName("clearButton") self.horizontalLayout.addWidget(self.clearButton) self.EAXlineEdit = QtWidgets.QLineEdit(self.tab) self.EAXlineEdit.setObjectName("EAXlineEdit") self.horizontalLayout.addWidget(self.EAXlineEdit) self.label = QtWidgets.QLabel(self.tab) self.label.setObjectName("label") self.horizontalLayout.addWidget(self.label) spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.gridLayout_2.addLayout(self.horizontalLayout, 0, 0, 1, 1) self.tabWidget.addTab(self.tab, "") self.tab_2 = QtWidgets.QWidget() self.tab_2.setObjectName("tab_2") self.gridLayout_4 = QtWidgets.QGridLayout(self.tab_2) self.gridLayout_4.setObjectName("gridLayout_4") self.textEdit = QtWidgets.QTextEdit(self.tab_2) self.textEdit.setObjectName("textEdit") self.gridLayout_4.addWidget(self.textEdit, 0, 0, 1, 1) self.gridLayout_3 = QtWidgets.QGridLayout() self.gridLayout_3.setObjectName("gridLayout_3") self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.pushButton = QtWidgets.QPushButton(self.tab_2) self.pushButton.setObjectName("pushButton") self.horizontalLayout_2.addWidget(self.pushButton) spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem1) self.pushButton_2 = QtWidgets.QPushButton(self.tab_2) self.pushButton_2.setObjectName("pushButton_2") self.horizontalLayout_2.addWidget(self.pushButton_2) self.gridLayout_3.addLayout(self.horizontalLayout_2, 0, 0, 1, 1) self.gridLayout_4.addLayout(self.gridLayout_3, 1, 0, 1, 1) self.tabWidget.addTab(self.tab_2, "") self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 482, 22)) self.menubar.setObjectName("menubar") self.menuFile = QtWidgets.QMenu(self.menubar) self.menuFile.setObjectName("menuFile") self.menuQuit = QtWidgets.QMenu(self.menubar) self.menuQuit.setObjectName("menuQuit") self.menuHelp = QtWidgets.QMenu(self.menubar) self.menuHelp.setObjectName("menuHelp") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.actionSave_Program = QtWidgets.QAction(MainWindow) self.actionSave_Program.setObjectName("actionSave_Program") self.actionLoad_Program = QtWidgets.QAction(MainWindow) self.actionLoad_Program.setObjectName("actionLoad_Program") self.menuFile.addAction(self.actionSave_Program) self.menuFile.addAction(self.actionLoad_Program) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuQuit.menuAction()) self.menubar.addAction(self.menuHelp.menuAction()) self.retranslateUi(MainWindow) self.tabWidget.setCurrentIndex(1) self.clearButton.clicked.connect(self.EAXlineEdit.clear) self.pushButton_2.clicked.connect( self.addRandomTextSlot) self.pushButton.clicked.connect(self.textEdit.clear) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.clearButton.setText(_translate("MainWindow", "Clear")) self.label.setText(_translate("MainWindow", "EAX")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Processor")) self.pushButton.setText(_translate("MainWindow", "Clear")) self.pushButton_2.setText(_translate("MainWindow", "Random Text")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Memory")) self.menuFile.setTitle(_translate("MainWindow", "File")) self.menuQuit.setTitle(_translate("MainWindow", "Quit")) self.menuHelp.setTitle(_translate("MainWindow", "Help")) self.actionSave_Program.setText(_translate("MainWindow", "Save Program")) self.actionLoad_Program.setText(_translate("MainWindow", "Load Program")) @pyqtSlot( ) def addRandomTextSlot( self ): self.textEdit.insertPlainText( "Hello World!" ) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_())
For simplicity, we have listed below only the lines that need to be edited, with proper indentation:
from PyQt5.QtCore import QObject, pyqtSlot class Ui_MainWindow( QObject): self.pushButton_2.clicked.connect( self.addRandomTextSlot) @pyqtSlot( ) def addRandomTextSlot( self ): self.textEdit.insertPlainText( "Hello World!" )
The addRandomTextSlot( self ) addition is the slot we attached to the Random Text push-button in the GUI, using Designer. The pyuic5 utility does not seem to generate code for it, and it's left up to us to do.
Try running the newly created file with Python 3:
python3 mainwindow.py
You should see the GUI as illustrated above. Flip between the two tabs to verify that both have been populated.
Create the Main Application
The -x option of the pyuic5 command generated the code (below) at the end of the mainwindow.py file:
if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_())
We use this directly to generate our app.py main file:
# app.py # D. Thiebaut # Main application for the Main Window PyQt5 example. # import sys from PyQt5 import QtGui, QtWidgets from mainwindow import Ui_MainWindow def main(): app = QtWidgets.QApplication( sys.argv ) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi( MainWindow ) MainWindow.show() sys.exit( app.exec_() ) main()
Running the App
Simply type
python3 app.py
to run the application. You should see a GUI appearing, as illustrated at the top of this page, that responds to user interactions. In particular, verify that the clear buttons work, and that the Random Text button prints "Hello World!" in the TextEdit widget.
Congrats, you have a simple template for building a more sophisticated main window in PyQt5!
Deploying
Deploying the newly created project can be done with PyInstaller.