Summary: in this tutorial, you’ll learn how to use the Qt Designer tool to design user interfaces for PyQt applications.
Install the PyQt tools
PyQt6 tools are compatible with Python 3.9 at the time of writing this tutorial. Therefore, you need to install Python 3.9 to continue the tutorial.
Note that if you have Python 3.10 or higher, you can install Python 3.9 in a separate directory and use PyQt6 tools. For example, you can install Python 3.9 in the C:\Python39 directory on Windows.
Create a new virtual environment
First, create a directory to host the PyQt6 projects e.g., D:\pyqt6
mkdir pyqt6
Code language: Python (python)
Second, create a virtual environment using Python 3.9 using the venv
module:
python -m venv D:\pyqt6\pyqt6-env
Code language: Python (python)
Activate the virtual environment
First, navigate to the pyqt6-env
virtual environment directory:
cd D:\pyqt6\pyqt6-env
Code language: Python (python)
Second, navigate to the Scripts
folder:
cd Scripts
Code language: Python (python)
Third, activate the virtual environment by executing the activate.bat file:
activate
Code language: Python (python)
It’ll show the following on Windows:
(pyqt6-env) d:\pyqt6\pyqt6-env\Scripts>
Code language: Python (python)
Install PyQt6 and its tools
First, execute the following command to install pyqt6
package in the pyqt6-env
virtual environment:
pip install pyqt6
Code language: Python (python)
Second, install the pyqt6-tools
package that contains the Qt Designer and other related tools:
pip install pyqt6-tools
Code language: Python (python)
The pyqt-tools
package will install the Qt Designer in the following location:
D:\pyqt6\pyqt6-env\Lib\site-packages\qt6_applications\Qt\bin\designer.exe
Code language: Python (python)
Third, execute the pyuic6
command (within the pyqt6-env
virtual environment) to check the version:
pyuic6 -V
Code language: Python (python)
And you’ll see the following output:
6.1.0
Code language: Python (python)
The pyuic6 is a tool for converting a design file (.ui
) generated by Qt Designer to a Python file (.py
).
Launch the Qt Designer
From the Shell, type the designer
command to launch the Qt Designer:
(pyqt6-env) d:\pyqt6\pyqt6-env\Scripts>designer
Code language: Python (python)
The Qt Designer will look like this:
Creating a login form
We’ll create a simple login form using the Qt designer and load it into our Python program.
First, select File > New
or press Ctrl-N
keyboard shortcut to open the New Form dialog:
Second, select the Widget
from the templates\forms
and click the Create
button:
It’ll create a QWidget
as follows:
You can set the layout for the widget, and drag and drop widgets from the Widget Box to the form.
Setting widget properties
In the Property Editor, you can set a name for the widget e.g., login_form
and the window title:
Adding widgets to the login form
First, add the widgets QLabel
, QLineEdit
, and QPushButton
to the form:
The following table lists the fields, their types, and names:
Field | Widget | Object Name |
---|---|---|
Login Window | QWidget | login_form |
Email Address | QLineEdit | email_line_edit |
Password | QLineEdit | password_line_edit |
Login Button | QPushButton | btn_login |
Second, set the echo mode of the password field to Password
:
Third, right-click the widget and set its layout to Form Layout:
The form will change to the following:
Fourth, change the size of the Login
button by setting its Horizontal Size Policy to Fixed:
Fifth, save the form to the D:\pyqt6
directory as login_form.ui
file.
Sixth, select Form > Preview...
menu or the keyboard shortcut Ctrl-R
to preview the form:
Finally, close the Qt Designer.
There’re two ways to use the login_form
.ui from a Python program:
- Convert the .ui file to Python code and use the generated code from the program.
- Directly use the .ui file in the program.
Converting .ui file to Python code
First, execute the following command to convert the login_form.ui
file to login_form.py
file:
pyuic6 -o login_form.py login_form.ui
Code language: Python (python)
Note that you need to run the pyuic6
from the pyqt6-env virtual environment.
The pyuic6
generated the login_form.py
from the login_form.ui
file. The login_form.py
contains the following generated Python code:
# Form implementation generated from reading ui file 'login_form.ui'
#
# Created by: PyQt6 UI code generator 6.1.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_login_form(object):
def setupUi(self, login_form):
login_form.setObjectName("login_form")
login_form.resize(269, 108)
self.formLayout = QtWidgets.QFormLayout(login_form)
self.formLayout.setObjectName("formLayout")
self.label = QtWidgets.QLabel(login_form)
self.label.setObjectName("label")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label)
self.email_line_edit = QtWidgets.QLineEdit(login_form)
self.email_line_edit.setObjectName("email_line_edit")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.email_line_edit)
self.label_2 = QtWidgets.QLabel(login_form)
self.label_2.setObjectName("label_2")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_2)
self.password_line_edit = QtWidgets.QLineEdit(login_form)
self.password_line_edit.setEchoMode(QtWidgets.QLineEdit.EchoMode.Password)
self.password_line_edit.setObjectName("password_line_edit")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.password_line_edit)
self.btn_login = QtWidgets.QPushButton(login_form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.btn_login.sizePolicy().hasHeightForWidth())
self.btn_login.setSizePolicy(sizePolicy)
self.btn_login.setObjectName("btn_login")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.ItemRole.FieldRole, self.btn_login)
self.retranslateUi(login_form)
QtCore.QMetaObject.connectSlotsByName(login_form)
def retranslateUi(self, login_form):
_translate = QtCore.QCoreApplication.translate
login_form.setWindowTitle(_translate("login_form", "Login"))
self.label.setText(_translate("login_form", "Email Address"))
self.label_2.setText(_translate("login_form", "Password"))
self.btn_login.setText(_translate("login_form", "Login"))
Code language: Python (python)
It’s important to note that you should never manually change the login_form.py file. Because all your manual adjustments will be lost if you edit the login_form.ui
in the Qt Designer and regenerate the login_form.py
again.
Second, create the login.py
file and import the login_ui.py
file:
import sys
from PyQt6.QtWidgets import QApplication, QWidget
from login_form import Ui_login_form
class Login(QWidget):
def __init__(self):
super().__init__()
# use the Ui_login_form
self.ui = Ui_login_form()
self.ui.setupUi(self)
# show the login window
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
login_window = Login()
sys.exit(app.exec())
Code language: Python (python)
How it works.
- Import
Ui_login_form
class from thelogin_form.py
file - Create a new instance of the
Ui_login_form
and call thesetupUi()
method to set up the user interfaces.
Third, execute the login.py
file:
python login.py
Code language: Python (python)
It’ll show the login window:
Referencing child widgets
To use the child widgets of Ui_login_form
widget, you reference their names using the self.ui
variable.
For example, you can add a simple authentication when the user enters an email address and password and click the Login button as follows:
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QMessageBox
from login_form import Ui_login_form
class Login(QWidget):
def __init__(self):
super().__init__()
# use the Ui_login_form
self.ui = Ui_login_form()
self.ui.setupUi(self)
# authenticate when the login button is clicked
self.ui.btn_login.clicked.connect(self.authenticate)
# show the login window
self.show()
def authenticate(self):
email = self.ui.email_line_edit.text()
password = self.ui.password_line_edit.text()
if email == '[email protected]' and password == '123456':
QMessageBox.information(self, 'Success',"You're logged in!")
else:
QMessageBox.critical(self, 'Error',"Invalid email or password.")
if __name__ == '__main__':
app = QApplication(sys.argv)
login_window = Login()
sys.exit(app.exec())
Code language: Python (python)
How it works.
First, connect the clicked signal of the button to the authenticate method. Notice that we reference the btn_login
button via the self.ui
variable:
self.ui.btn_login.clicked.connect(self.authenticate)
Code language: Python (python)
Second, define the authenticate()
method that gets values from the email_line_edit
and password_line_edit
and perform a simple check of these values against hard-coded values:
def authenticate(self):
email = self.ui.email_line_edit.text()
password = self.ui.password_line_edit.text()
if email == '[email protected]' and password == '123456':
QMessageBox.information(self, 'Success',"You're logged in!")
else:
QMessageBox.critical(self, 'Error',"Invalid email or password.")
Code language: Python (python)
Security Notice: Never do this in real applications.
Besides creating an instance of the Ui_login_form
inside the login window, you can inherit the Ui_login_form
window using multiple inheritances and directly reference the child widgets like this:
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QMessageBox
from login_form import Ui_login_form
class Login(QWidget,Ui_login_form):
def __init__(self):
super().__init__()
# setup the UI
self.setupUi(self)
# authenticate when the login button is clicked
self.btn_login.clicked.connect(self.authenticate)
# show the login window
self.show()
def authenticate(self):
email = self.email_line_edit.text()
password = self.password_line_edit.text()
if email == '[email protected]' and password == '123456':
QMessageBox.information(self, 'Success',"You're logged in!")
else:
QMessageBox.critical(self, 'Error',"Invalid email or password.")
if __name__ == '__main__':
app = QApplication(sys.argv)
login_window = Login()
sys.exit(app.exec())
Code language: Python (python)
Using .ui file directly
Another way to use the design generated by the Qt Designer is to load the .ui
file directly using the loadUi()
function of the uic
module:
from PyQt6.QtWidgets import QApplication, QWidget, QMessageBox
from PyQt6 import uic
import sys
class Login(QWidget):
def __init__(self):
super().__init__()
self.ui = uic.loadUi('login_form.ui', self)
# authenticate when the login button is clicked
self.ui.btn_login.clicked.connect(self.authenticate)
self.show()
def authenticate(self):
email = self.email_line_edit.text()
password = self.password_line_edit.text()
if email == '[email protected]' and password == '123456':
QMessageBox.information(self, 'Success',"You're logged in!")
else:
QMessageBox.critical(self, 'Error',"Invalid email or password.")
if __name__ == '__main__':
app = QApplication(sys.argv)
login_window = Login()
sys.exit(app.exec())
Code language: Python (python)
The loadUi()
function returns an instance of the QWidget
and you can reference the child widgets via the self.ui
variable.
When you should use Qt Designer
The .ui file generated by the Qt designer creates an abstraction layer between the available widget and the code that consumes it.
Therefore, if you are starting out with PyQt, you should code the UI
manually instead of using Qt Designer. By doing this, you know exactly what widgets are available in the application.
However, if you’re familiar with PyQt and work on a large application, you should use Qt Designer to create a good design and improve productivity.
Summary
- Use Qt Designer to design user interfaces for large applications.
- Use the
pyuic6
tool to convert a .ui file into a Python source code file. - Use
loadUi()
function of theuic
module to load the.ui
file directly.