Python GUI — Building a Simple Application with PyQt and Qt Designer

This article is intended for those who are just starting their acquaintance with creating graphical user interface (GUI) applications in Python. In it, we’ll cover the basics of using PyQt in conjunction with Qt Designer. Step by step, we will create a simple Python GUI application that will display the contents of the selected directory.

Image for post
Image for post

What do we need?

We need PyQt and Qt Designer, and Python, of course.

This article uses PyQt5 with Python 3, but there are no major differences between PyQt and PySide or their Python 2 versions.

Windows: PyQt can be downloaded here. It comes with Qt Designer.

macOS: You can install PyQt using Homebrew:

$ brew install pyqt5

You can download the package with most of the Qt components and tools, which contains Qt Designer, at this link.

Linux: Everything you need is probably in your distribution’s repositories. Qt Designer can be installed from the Application Center, but PyQt has to be installed through the terminal. Install everything that we need with one command, for example, like this:

# For Fedora:
$ sudo dnf install python3-qt5 qt-creator
# For Debian/Ubuntu:
$ sudo apt install python3-qt5 pyqt5-dev-tools qtcreator

Once you’re done with your preparations, open a command prompt / terminal and make sure you can use the command pyuic5. You should see the following:

$ pyuic5
Error: one input ui-file must be specified

Oops! If you see a message that there is no such command or something like that, try googling the solution for the problem for your operating system and version of PyQt.

If you are using Windows, then most likely the path C:\Python36\Scripts(change 36 to your Python version) is not written in your PATH. Check out this Stack Overflow thread to find out how to fix the problem.

Design

The basics of PyQt

Now that we are all set to work, let’s start with a simple design.

Open Qt Designer, where you will see a new form dialog, select Main Window, and click Create.

Python GUI with PyQt — Dialog window
Python GUI with PyQt — Dialog window

After that, you should have a form — a template for a window, the size of which can be changed, and where you can insert objects from the widget window, etc. Check out the interface, it’s pretty simple.

Now let’s resize our main window a little because we don’t need it to be that big. Also, let’s remove the automatically added menu and status bar since they won’t be useful in our application.

All form elements and their hierarchy are displayed by default on the right side of the Qt Designer window under the name Object Inspector. You can easily delete objects by right-clicking on them in this window. Alternatively, you can select them in the main form and press the DEL key on your keyboard.

Python GUI with PyQt — Main interface
Python GUI with PyQt — Main interface

As a result, we have an almost empty form. The only remaining object is centralwidget, but we'll need it, so we won't do anything with it.

Now drag the List Widget (not List View (!)) and Push Button from the Widget Box somewhere in the main form.

Layouts

Instead of using fixed positions and sizes of elements in your application, it’s better to use layouts. The fixed positions and sizes will look good for you (until you resize the window), but you can never be sure that everything will be the same on other machines and / or operating systems.

Layouts are containers for widgets that will hold them in position relative to other elements. Therefore, when the window is resized, the size of the widgets will also change.

Let’s create our first form without using layouts. Drag the list box and button on the form and resize them to look like this:

Python GUI PyQt — Qt Designer Menu
Python GUI PyQt — Qt Designer Menu

Now on the Qt Designer menu click on Form, then select Preview and you will see something similar to the screenshot above. Looks good, doesn’t it? But this is what happens when we resize the window:

Python GUI PyQt — Main Window View
Python GUI PyQt — Main Window View

Our objects remained in the same places and retained their sizes, despite the fact that the size of the main window has changed and the button is almost invisible. This is why you should use layouts in most cases. Of course, there are times when, for example, you want a fixed or min / max width for an object. But in general, when developing an application, it is better to use layouts.

The main window already supports layouts, so we don’t need to add anything to our form. Just right click on the Main Window in the Object Inspector and select Lay outLay out vertically. Alternatively, you can right-click on an empty area in the form and select the same options:

Python GUI PyQt — Editing Layout
Python GUI PyQt — Editing Layout

Your elements should be in the same order as before the changes were made, but if they are not, then simply drag and drop them to the desired location.

Since we used vertical placement, all the elements that we add will be placed vertically. Placements can be combined to achieve the desired result. For example, placing two buttons horizontally in a vertical one would look like this:

Python GUI PyQt — Placing two buttons
Python GUI PyQt — Placing two buttons

If you are unable to move an element in the main window, you can do so in the Object Inspector .

Final touches

Now, thanks to the vertical placement, our elements are aligned correctly. The only thing left to do (but not necessary) is to change the name of the elements and their text.

In a simple application like this with only a list and a button, changing the names is not necessary, since it is easy to use anyway. Nevertheless, the correct naming of elements is something to get used to from the very beginning.

Element properties can be changed in the Property Editor section.

Hint: You can resize, move, or add frequently used elements to the Qt Designer interface to speed up your workflow. You can add hidden / hidden parts of the interface through the View menu item.

Click on the button you added to the form. You should now be able to see all the properties for this item in the Property Editor. At the moment we are objectNamealso interested textin the section QAbstractButton. You can collapse sections in the Property Editor by clicking on the section name.

Change the value objectNameto btnBrowseand textto Select a folder.

It should look like this:

Python GUI PyQt — Choosing a Folder
Python GUI PyQt — Choosing a Folder

The name of the list object is listWidget, which is fine in this case.

Save the design as design.ui in the project folder.

Turning design into code

Of course, you can use the .ui-files directly from Python code, but there is another way that might seem easier. It is possible to convert the code .uifile into a Python file, which we can then import and use. For this we use the command pyuic5 from the terminal / command line.

To convert a .ui.file to a python file named design.py, use the following command:

$ pyuic5 path/to/design.ui -o output/path/to/design.py

Writing the code

Now we have a file design.py with the desired part of our application design and we can start working on creating its logic.

Create a file main.py in the folder where it is located design.py.

Using a design

For a Python GUI application, you need the following modules:

We also need the design code we created earlier, so we’ll import that too:

Since the design file will be completely overwritten every time the design is changed, we will not change it. Instead, we’ll create a new class ExampleAppthat we combine with the design code to use all of its functionality:

In this class, we will interact with the interface elements, add connections, and whatever else we need. But first, we need to initialize the class when the code runs. We’ll deal with this in the function main():

And to perform this function, we will use the familiar construction:

As a result, main.py it looks like this:

If you run this code, then our application will start!

$ python3 main.py
Python GUI PyQt — App running
Python GUI PyQt — App running

But clicking on the button does nothing, so we have to figure it out.

Adding functionality to our Python GUI application

NoteAll further code is written inside the class ExampleApp.

Let’s start with the Select a folder button. You can attach an event like clicking a button to a function as follows:

Add this line to a __init__class method ExampleAppto bind when the application starts. Now let's take a closer look at it:

  • self.btnBrowse: here btnBrowseis the name of the object that we have defined in Qt Designer. self speaks for itself and means belonging to the current class;
  • clicked - the event that we want to bind. Different elements have different events, for example, list widgets have itemSelectionChanged, etc .;
  • connect() - the method that binds the event to the call of the passed function;
  • self.browse_folder- just a function (method) that we described in the class ExampleApp.

To open the folder selection dialog, we can use the built-in method QtWidgets.QFileDialog.getExistingDirectory:

If the user selects a directory, the variable will directory be assigned the absolute path to the selected directory, otherwise it will be equal to None. To avoid executing the code further, if the user closes the dialog, we use the command if directory:.

To display the contents of the directory, we need to import os:

import os

And get the list of contents like this:

os.listdir(path)

To add elements to listWidgetwe use the method addItem(), and to remove all elements we have self.listWidget.clear().

As a result, the function browse_foldershould look like this:

Now, if you run the application, click on the button and select the directory, we will see:

Python GUI PyQt — Work of the app
Python GUI PyQt — Work of the app

This is how the whole code of our Python GUI application looks like:

These were the basics of using Qt Designer and PyQt to develop a Python GUI application. Now you can safely redesign your application and use the command pyuic5without fear of losing your code.

Written by

Bioinformatician at Oncobox Inc. (@oncobox). Research Associate at Moscow Institute of Physics and Technology (@mipt_eng).

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store