Qt Designer

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:

Qt Designer

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:

Qt Designer - New

Second, select the Widget from the templates\forms and click the Create button:

Qt Designer - Create a Widget

It’ll create a QWidget as follows:

Qt Designer - Form

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

Qt Designer - Widget Properties

and the window title:

Qt Designer -Window Title

Adding widgets to the login form

First, add the widgets QLabel, QLineEdit, and QPushButton to the form:

Qt Designer - widgets

The following table lists the fields, their types, and names:

FieldWidgetObject Name
Login WindowQWidgetlogin_form
Email AddressQLineEditemail_line_edit
PasswordQLineEditpassword_line_edit
Login ButtonQPushButtonbtn_login

Second, set the echo mode of the password field to Password:

Qt Designer - Password field

Third, right-click the widget and set its layout to Form Layout:

Qt Designer - Set Form Layout

The form will change to the following:

Qt Designer - Form Layout

Fourth, change the size of the Login button by setting its Horizontal Size Policy to Fixed:

Qt Designer - Change the button size

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:

Qt Designer - Preview

Finally, close the Qt Designer.

There’re two ways to use the login_form.ui from a Python program:

  1. Convert the .ui file to Python code and use the generated code from the program.
  2. 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.

  1. Import Ui_login_form class from the login_form.py file
  2. Create a new instance of the Ui_login_form and call the setupUi() 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:

Qt Designer - 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 == 'john@test.com' 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 == 'john@test.com' 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 == 'john@test.com' 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 == 'john@test.com' 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 the uic module to load the .ui file directly.
Did you find this tutorial helpful ?