How to Build User Interfaces with Python — PyQt Basics

Are you tired of all the programs you create running in the console? Try graphical interfaces! It’s very easy to do in Python.
PyQt or Tkinter?
PyQt and Tkinter are the two main libraries you can use to build user interfaces with Python. Neither is better than the other, but depending on what you want to achieve one or the other may be more suitable
Tkinter:
- Simple and light. This allows you to quickly and easily set up a graphical application.
- Fewer possibilities than PyQt.
- GUIs are difficult to customize.
- Works with events to manage interactions.
PyQt:
- Complex and heavy. The learning curve isn’t the same as the one of Tkinter but once you master PyQt you can build everything.
- GUIs are easily customizable using style sheets (CSS).
- Works with a system of signals and slots which can be a bit confusing for beginners.
It’s good to know both libraries, eventually to know how to use them both, and to decide which one to use depending on the project. Tkinter will be useful for small projects, that need to be set up quickly. PyQt will be preferable when the projects are larger or longer term.
Personally, if you had to learn one of the two, I would recommend PyQt. It takes longer to learn and get the hang of it, but the possibilities are endless when you master it well.
PyQt
Today, I’ll talk only about PyQt as it’s the purpose of the story. I’ll talk about Tkinter in another story.
Installation
You can install either PyQt5 or PyQt6. They are almost the same. PyQt6 is an upgrade of PyQt5 but it doesn’t change a lot of things.
pip install PyQt5
# or
pip install PyQt6First window
Let’s import some widgets first as we’ll need them to create our window (we’ll see in the next section what widgets are).
from PyQt5.QtWidgets import QApplication, QLabelA QApplication is a wrapper for a PyQt application. It’s the basic element of every Qt program. Let’s create our application:
import sys
app = QApplication(sys.argv)Why sys.argv?
These are the arguments passed at the execution of your script. You should know that you have to pass arguments to instantiate a QApplication, at least pass an empty list as an argument.
Now we’ll decorate our application a little:
label = QLabel("Hello")
label.show()A QLabel is a Qt widget displaying some text? We create it, then call the show method to display it.
Then, we have to execute our application:
app.exec_()The full code for creating a simple window is:
import sys
from PyQt5.QtWidgets import QApplication, QLabel
app = QApplication(sys.argv)
label = QLabel("Hello")
label.show()
app.exec_()Widgets
Widgets are everything you see in a PyQt application. If you put text, it is a widget, buttons are widgets, sliders are widgets, etc… Even your window is a widget.
Widgets can be nested within each other. For example, my window is a widget containing other widgets like buttons, which in turn contain widgets like text.
There are a lot of them, and you will certainly use a lot of them if you make a Qt application. We’ll see the QLabel and the QPushButton, for the others, you’ll have to dig into the documentation! (PyQt5 doc)
QLabel
It is simply a widget containing text. We pass the text to display when we build it.
label = QLabel("Hello")QPushButton
It is a widget representing a button. In the same way as a QLabel, we pass it the text of the button.
button = QPushButton("I'm a button!")Is that all? How do you assign actions when you click on the button?
We’ll see later when we’ll study the signals and the slots :)
Layouts
Layouts are also widgets. However, they are a bit special because they have no graphical appearance. They simply tell you how to arrange the widgets in the window.
For example, imagine that you have a cabinet with several drawers. This cupboard can have several doors, several drawers, etc… And you can store objects in them in the dedicated slots. In this case, your items will be well organized and arranged according to the structure defined by the cabinet.
This is pretty much what you can do with layouts, except that, unlike the wardrobe, the layouts and drawers are invisible, only the objects contained in them are visible.
Let’s start by creating our first layout, a QVBoxLayout. This is a layout that allows us to stack widgets on top of each other.
from PyQt5.QtWidgets import QVBoxLayout
vbox = QVBoxLayout()Now that we have created our vertical storage cabinet, we need to fill it with items.
button1 = QPushButton("Button 1")
button2 = QPushButton("Button 2")vbox.addWidget(button1)
vbox.addWidget(button2)Our cabinet is filled with two buttons that will be displayed vertically. But now, what do we do? Our wardrobe has to be in a house to be useful (well, not necessarily, but logically so). Our house is the window of the application, it is in it that we can put all our wardrobes. Be careful though, we have to distinguish the window from the application.
We start by creating an application, in which we create a window, and to which we add our cabinet (layout). Finally, we display our window, and we execute the whole thing:
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton
app = QApplication([])
window = QWidget()
vbox = QVBoxLayout()
button1 = QPushButton("Button 1")
button2 = QPushButton("Button 2")
vbox.addWidget(button1)
vbox.addWidget(button2)
window.setLayout(vbox)
window.show()
app.exec()Run this code and you’ll see a beautiful window containing two buttons.
Styling your app
If you want to style your app, you can do it in several ways:
- Base styles.
- Colors palettes.
- Style sheets.
Base styles
PyQt offers several basic styles, which can be switched easily. They completely change the appearance of your application. Here are some of them:
- Fusion
- Windows
- WindowsVista
- Macintosh
- etc…
To apply a style, we use the method setStyleof our application:
app.setStyle("Windows")Colors palettes
Maybe you just want to change the colors instead of redesigning the whole style. For this we use QPalette. It allows you to do the color mapping. For example:
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPalette
palette = QPalette()
palette.setColor(QPalette.ButtonText, Qt.green)
app.setPalette(palette)In this example, we changed the color of every button’s text in our application and set it to green.
You can find all possible mappings in QPalette documentation.
Style sheets
Finally, the most complete way to modify the design of a PyQt application is by using style sheets. To do this, simply store your stylesheet in a string, and modify the style like this:
stylesheet = "QPushButton { margin-bottom: 5ex; }"
app.setStyleSheet(stylesheet)So, you can create a .css file, fill it with styles and then you extract its content and use it as a PyQt style sheet.
Signals and slots
These concepts are perhaps the hardest to understand in PyQt. A signal is sent when an action is performed, and a slot is an action that executes in response to that signal. For example, when a button is clicked, it sends a signal to say that the button was clicked, and it is possible to connect that to a slot to display text in response to that click, or to start a download, etc…
PyQt offers many signals with its widgets. For example, the signal mentioned above can be retrieved in this way:
button = QPushButton("Hello")
button.clicked.connect(...)So, we have this syntax: widget.signal.connect(function) .
If I want to display console text when I click on my button, I do it this way:
def hello():
print("hello")
button.clicked.connect(hello)You always have to connect a function. So if I try to do this:
button.clicked.connect(hello())I will get an error because hello() is not a function, but the value returned by hello. So this is where lambda functions become useful, so you can avoid writing too many basic functions.
button.clicked.connect(lambda x: print("hello"))You can find more information about the signals of each widget in the PyQt documentation!
Final note
There is so much to say about PyQt. I can’t tell you anything in one story, perhaps there will be more. While waiting, just practice because this library may be hard to understand but once you get the trick everything becomes easier.
Good luck with PyQt!





