© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2022
J. M. WillmanBeginning PyQthttps://doi.org/10.1007/978-1-4842-7999-1_2

2. Building a Simple GUI

Joshua M Willman1  
(1)
Sunnyvale, CA, USA
 

Hello again! GUIs are designed to handle specific tasks, such as writing and editing documents or playing videos. Creating any kind of UI can seem like a formidable task with all the different widgets there are to consider. Widgets are the buttons, checkboxes, sliders, and other components that users use to interact with the GUI.

In order to help you learn about the different kinds of widgets and understand when you might want to use them, each chapter will utilize different widgets and apply them to one or more GUI projects. Whenever a new widget is introduced, you will also apply that component in a smaller practical application before using them in larger GUIs. For some larger applications, we will also discuss the process for designing and arranging the widgets in the application’s window.

In this chapter, you will
  • Begin learning about widgets in PyQt and find out how to use them in your GUIs

  • Consider the design process for a simple GUI application

  • Build basic GUIs with primarily the QLabel widget

  • See how to organize widgets in a GUI using the move() method

Let’s begin by learning about a very fundamental widget.

The QLabel Widget

After learning how to create a window in Chapter 1, we can move forward and add more functionality with widgets. For this chapter, we will focus mainly on using QLabel as it is a widget that you will use in almost every GUI you develop. A QLabel object acts as a non-editable placeholder to display plain or rich text, hyperlinks, images, or GIFs. It is also useful for creating labels around other widgets to specify their roles or give them titles.

The GUI you will make, seen in Figure 2-1, demonstrates how to use QLabel to create both text and image labels and will act as your Hello World for adding widgets in PyQt.
Figure 2-1

Example of using QLabel widgets to place images and text in a window

Note

For this and other examples in this chapter, you will need to download the images folder and its contents from the GitHub repository.

Explanation for Using QLabel

Let’s begin by using the empty window script you created in Chapter 1 and use it as the foundation for creating Listing 2-1.

Note

As applications in this book grow in complexity, programs will be broken up into more manageable parts and built piece by piece to promote learning and understanding of the code. Many of the programs will start by using the empty window script from Chapter 1 as a starting point. If you get an error because a method or variable is missing while running a section of code, don’t fear. Keep coding and following along with each section of code to build the complete application. For example, you will need the code from Listings 2-1 to 2-2 to complete this program.

# labels.py
# Import necessary modules
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLabel
from PyQt6.QtGui import QPixmap
class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initializeUI()
    def initializeUI(self):
        """Set up the application's GUI."""
        self.setGeometry(100, 100, 250, 250)
        self.setWindowTitle("QLabel Example")
        self.setUpMainWindow()
        self.show()
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec())
Listing 2-1

Setting up the main window to show how to use QLabel widgets

First, let’s import the modules we need. To create the window, we need to import another PyQt class from the QtWidgets module, the QLabel class.

This time we also need to import the QtGui module. The QtGui module handles numerous graphic elements used in GUIs. QPixmap is a Qt class that is optimized for showing images on the screen and is useful for displaying an image on a QLabel object.

You’ll need to create a MainWindow class that inherits from the QWidget. If you copied the script from Chapter 1, simply change the name of the EmptyWindow class to MainWindow. Next, initialize the size of the window with setGeometry() and set the title of our GUI using setWindowTitle().

Note

Qt is filled with numerous class methods called accessors, also referred to as getters, for retrieving values and mutators, also called setters, for changing values. You have already seen two setter examples. To change the size of a widget or widget, you can use the setter setGeometry(). If you wanted to retrieve that value at any time, you could use the getter geometry(). Setter and getter methods follow that pattern in PyQt, where setters have the word set in the method name, and the getter removes the word set and replaces the first letter with a lowercase one.

Next, call the method setUpMainWindow(), which is used for not only setting up and arranging the widgets in the main window but for structuring the code as well. This method is created in Listing 2-2. Then we use the show() method to display the window. To set up the application, first create a QApplication object. Then initiate the window. Next, use exec() to begin the event loop. Finally, sys.exit() is used to handle safely closing the program.

The next thing to do is to create the MainWindow method, setUpMainWindow().

Note

Going by PEP 8, the Style Guide for Python Code, function names should be lowercase and separated with an underscore. The guidelines also state that mixedCase is also allowed if that is the prevailing style. This book will use mixedCase for function and method names to follow along with styles used in Qt and PyQt. More information about PEP 8 can be found at www.python.org/dev/peps/pep-0008/#prescriptive-naming-conventions.

# labels.py
    def setUpMainWindow(self):
        """Create QLabel to be displayed in the main window."""
        hello_label = QLabel(self)
        hello_label.setText("Hello")
        hello_label.move(105, 15)
        image = "images/world.png"
        try:
            with open(image):
                world_label = QLabel(self)
                pixmap = QPixmap(image)
                world_label.setPixmap(pixmap)
                world_label.move(25, 40)
        except FileNotFoundError as error:
            print(f"Image not found. Error: {error}")
Listing 2-2

The setUpMainWindow() method for displaying text and image labels

First, you must create a QLabel object. By passing self as a parameter to QLabel, you set the MainWindow class as the parent of the label. This will be helpful for displaying and arranging the widget in the parent object. Next, specify what the label will say using setText(). Here, the text is set to "Hello". In the following line, we use the move() method to arrange the label in the window.

PyQt has a number of layout techniques, including horizontal layouts, grid layouts, and absolute positioning . We’ll take an in-depth look at those classes in Chapter 4. For the programs created in this chapter, we will be using absolute positioning with the move() method. With move(), you only need to specify the x and y pixel values of where you want to place the widgets.

Imagine the main window as a graph where its upper-left corner is point (0,0). The x and y values you choose in move() refer to the point where the widget's top-left corner is placed in the main window. For our text label, we specify the values to be x=105 and y=15. This is definitely not the best method for arranging widgets in a window for a number of reasons. For one, it is complicated and involves using trial and error for setting your widget’s position. Another reason has to deal with resizing a window. If you were to adjust the size of the window by dragging on the bottom-right corner, you’ll notice that the widgets don’t move or stretch. Qt’s layout classes are great for handling this and other issues. We’ll discuss using the layout classes in Chapter 4.

You might think learning using move() is a waste of time, but it can be very useful to understand how to use pixel values to manipulate widgets, especially when we begin dealing with more advanced topics like animations and graphics classes.

The image is loaded in a similar fashion, creating a world_label object to be placed in the main window. Then we construct a QPixmap of the image and use setPixmap() to set the image displayed onto the world_label. The image’s absolute location is set using move(). An exception is thrown if the image cannot be found.

Each of PyQt’s different classes has their own methods that can be used to customize and change their look and functionality. In the Appendix, you can find a list of the widgets used in this book along with some of the more common methods you are likely to use to modify them.

Once you run the program, you should see a window like Figure 2-1 appear on your screen. In the next section, you’ll build a slightly more complex GUI using QLabel widgets.

Project 2.1 – User Profile GUI

A user profile is used to visually display personal data. The data in the profile helps to associate certain characteristics with that user and assists others in learning more about that individual. Depending upon the goal of the application, the information and appearance of the profile will change.

User profiles like the one displayed in Figure 2-2 often have a number of parameters that are either mandatory or optional and allow for some level of customization to fit the preferences of the user, such as a profile image or background colors. Many of them contain similar features, such as the user’s name or an “About” section.
Figure 2-2

The User Profile GUI that displays a user’s information

In the next section, we’ll break apart Figure 2-2 and think about how the label widgets will be arranged in the window.

Designing the User Profile GUI

Typical user profile applications often use a combination of different elements, both interactive and static. The schematic in Figure 2-3 focuses on utilizing solely static QLabel widgets for displaying information in the window.

If you compare Figure 2-3 with Figure 2-2, you will notice the similarity with how they are arranged. The user interface can be divided into two parts. The upper portion uses QLabel objects that display a profile image that lies on top of a background image.
Figure 2-3

Schematic for the User Profile GUI

The bottom portion shows the user’s information with multiple QLabel widgets, with the textual information arranged vertically and broken down into smaller sections, delineated by the use of different font sizes.

Explanation for the User Profile GUI

Similar to the last application, we’ll begin by using the template GUI from Chapter 1 as the foundation for the User Profile’s main window in Listing 2-3.
# user_profile.py
# Import necessary modules
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLabel
from PyQt6.QtGui import QFont, QPixmap
class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initializeUI()
    def initializeUI(self):
        """Set up the application's GUI."""
        self.setGeometry(50, 50, 250, 400)
        self.setWindowTitle("2.1 - User Profile GUI")
        self.setUpMainWindow()
        self.show()
# Run program
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec())
Listing 2-3

Code for setting up the User Profile GUI’s main window

For the User Profile GUI, import the same classes and modules as the earlier application along with the addition of one new class, the QFont class from the QtGui module, which allows for us to modify the size and types of fonts in our application. This is perfect for creating the different header sizes.

Before creating setUpMainWindow(), let’s create a separate method in MainWindow, seen in Listing 2-4, that will handle loading the different images and creating QLabel objects to display them.
# user_profile.py
    def createImageLabels(self):
        """Open image files and create image labels."""
        images = ["images/skyblue.png",
                  "images/profile_image.png"]
        for image in images:
            try:
                with open(image):
                    label = QLabel(self)
                    pixmap = QPixmap(image)
                    label.setPixmap(pixmap)
                    if image == "images/profile_image.png":
                        label.move(80, 20)
            except FileNotFoundError as error:
                print(f"Image not found. Error: {error}")
Listing 2-4

Code for createImageLabels() in the User Profile GUI

The images list contains the specific file locations that will be used for both the blue background and the user’s profile image in the top part of the window. Using a for loop, iterate through the list’s items, create a QLabel object for each, instantiate a QPixmap object, set the pixmap for the label, and if the image is the profile image, center it in the window using move(). Using move() and absolute positioning, you can easily overlap images, but you will need to load the images in order from the bottom-most image to the top-most.

We can now create the MainWindow method setUpMainWindow() in Listing 2-5 where createImageLabels() will be called.
# user_profile.py
    def setUpMainWindow(self):
        """Create the labels to be displayed in the window."""
        self.createImageLabels()
        user_label = QLabel(self)
        user_label.setText("John Doe")
        user_label.setFont(QFont("Arial", 20))
        user_label.move(85, 140)
        bio_label = QLabel(self)
        bio_label.setText("Biography")
        bio_label.setFont(QFont("Arial", 17))
        bio_label.move(15, 170)
        about_label = QLabel(self)
        about_label.setText("I'm a Software Engineer with 10 years
            experience creating awesome code.")
        about_label.setWordWrap(True)
        about_label.move(15, 190)
Listing 2-5

Code for the User Profile GUI’s setUpMainWindow() method

After the image labels are created, several QLabel objects for showing text are instantiated. For example, the user_label displays the user’s name using setText() in the window. You can set a QLabel widget’s font with the method setFont(). Be sure to pass a QFont object and specify the type of font and its size. The user_label is then centered in the window using move(). Other labels are created in a similar manner.

Listing 2-6 continues to create and arrange QLabel widgets in the main window.
# user_profile.py
        skills_label = QLabel(self)
        skills_label.setText("Skills")
        skills_label.setFont(QFont("Arial", 17))
        skills_label.move(15, 240)
        languages_label = QLabel(self)
        languages_label.setText("Python  |  PHP  |  SQL  |  JavaScript")
        languages_label.move(15, 260)
Listing 2-6

Arranging more labels in the setUpMainWindow() method

More labels are created. Notice how the x value in move() stays at 15, leaving a small space on the left side of the window, and the y value gradually increases, placing each subsequent label lower. More labels are added to the GUI in Listing 2-7.
# user_profile.py
        experience_label = QLabel(self)
        experience_label.setText("Experience")
        experience_label.setFont(QFont("Arial", 17))
        experience_label.move(15, 290)
        developer_label = QLabel(self)
        developer_label.setText("Python Developer")
        developer_label.move(15, 310)
        dev_dates_label = QLabel(self)
        dev_dates_label.setText("Mar 2011 - Present")
        dev_dates_label.setFont(QFont("Arial", 10))
        dev_dates_label.move(15, 330)
        driver_label = QLabel(self)
        driver_label.setText("Pizza Delivery Driver")
        driver_label.move(15, 350)
        driver_dates_label = QLabel(self)
        driver_dates_label.setText("Aug 2015 - Dec 2017")
        driver_dates_label.setFont(QFont("Arial", 10))
        driver_dates_label.move(15, 370)
Listing 2-7

Arranging even more labels in the setUpMainWindow() method

Running the application now, you will see a window appear like the one in Figure 2-2.

Summary

In this chapter, we discovered how to add and arrange widgets in a GUI window. The QLabel widget is a fundamental class and is not only great for displaying text but can also be used with other PyQt classes, such as QPixmap for displaying images or QFont for changing the label’s text style or size. Each one of the PyQt classes includes various methods for extending their capabilities and appearance. Examples of those can be found in the Appendix.

In the next chapter, we’ll explore a number of different widget classes, including QPushButton and QLineEdit, that will allow users to interact with the applications that you develop.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset