본문 바로가기
Mastering-GUI-Programming

Deep Dive into PyQt

by 자동매매 2023. 3. 8.

1 Section 1: Deep Dive into PyQt

In this section, you will explore the core features of PyQt. By the end of this section, you should be comfortable with the basic design workflow and coding idioms involved in writing PyQt applications and feel confident in your ability to construct simple PyQt interfaces.

The following chapters are in this section:

1 Getting Started with PyQt

Welcome, Python programmer!

Python is a great language for system administration, data analysis, web services, and command-line programs; most likely you've already found Python useful in at least one of those areas. However, there is something truly satisfying about building the kind of GUI- driven application that an end user can readily identify as a program, and this skill should be in the toolbox of any master software developer. In this book, you're going to learn how you can use Python and the Qt framework to develop amazing applications—from simple data-entry forms to powerful multimedia tools.

We'll start our tour of these powerful technologies with the following topics:

  • Introducing Qt and PyQt
  • Creating Hello Qt – our first window
  • Creating a PyQt application template
  • Introducing Qt Designer

Technical requirements

For this chapter, and most of the rest of the book, you're going to need the following:

  • A PC running Microsoft Windows, Apple macOS, or a 64-bit flavor of GNU/Linux.
  • Python 3, available from http://www.python.org. The code in this book requires Python 3.7 or later.

Getting Started with PyQt Chapter 1

  • PyQt 5.12, which you can install from the Python Package Index using this command:

$ pip install --user PyQt5

Check out the following video to see the code in action: http://bit.ly/2M5OUeg

Installing Qt Designer

On Windows or macOS, Qt Designer is part of the Qt Creator IDE from the Qt company. This is a free IDE that you can use for coding, though, at the time of writing, it is mainly aimed at C++ and support for Python is rudimentary. The Qt Designer component can be used regardless of whether you do your coding in Qt Creator or not.

You can download an installer for Qt Creator from https://download.qt.io/official_ releases/qtcreator/4.9/4.9.0/.

Although the Qt company offers a similar standalone Qt installer for Linux, most Linux users will prefer to use packages from their distribution's repositories. Some distributions offer Qt Designer as a standalone application, while others include it in their Qt Creator packages.

This table shows the package that will install Qt Designer in several major distributions:

Distribution Package name
Ubuntu, Debian, Mint qttools5-dev-tools
Fedora, CentOS, Red Hat, SUSE qt-creator
Arch, Manjaro, Antergos qt5-tools
Introducing Qt and PyQt

Qt is a cross-platform application framework that was created for use with C++. Available in both commercial and open source licenses (General Public License (GPL) v3 and Lesser General Public License (LGPL) v3, specifically), it is widely used by open source projects such as KDE Plasma and Oracle VirtualBox, commercial software such as Adobe Photoshop Elements and Autodesk Maya, and even embedded software in products from companies such as LG and Panasonic. Qt is currently owned and maintained by the Qt company (https://www.qt.io).

In this book, we're going to be working with the open source release of Qt 5.12. If you're using Windows, macOS, or a major Linux distribution, you should not need to install Qt explicitly; it will be installed automatically when you install PyQt5.

Qt is officially pronounced cute, though many people say, Q T.

PyQt5

PyQt is a Python library that allows the Qt framework to be used in Python code. It was developed by Riverbank Computing under the GPL license, although commercial licenses can be purchased for those wanting to develop proprietary applications. (Note that this is a separate license from the Qt license.) It is currently supported on Windows, Linux, UNIX, Android, macOS, and iOS.

PyQt's bindings are generated automatically by a tool called SIP, so, to a large extent, working with PyQt is just like working with Qt itself, only in Python. In other words, the classes, methods, and other objects are all identical in usage, apart from the language syntax.

The Qt company has recently released Qt for Python (also known as PySide2), their own Python Qt5 library, under the terms of the LGPL. Qt for Python is functionally equivalent to PyQt5, and code can be ported between them with very few changes. This book will cover PyQt5, but what you learn can easily be applied to Qt for Python, should you need an LGPL library.

Working with Qt and PyQt

Qt is much more than a GUI library; it's an application framework. It contains dozens of modules with thousands of classes. It has classes to wrap simple data types such as dates, times, URLs, or color values. It has GUI components such as buttons, text entries, or dialog boxes. It has interfaces for hardware such as cameras or mobile sensors. It has a networking library, a threading library, and a database library. If anything, Qt is truly a second standard library!

Qt is written in C++ and designed around the needs of C++ programmers; it works well with Python, but Python programmers may find some of its concepts slightly foreign at first.

For example, Qt objects usually expect to work with data wrapped in Qt classes. A method that expects a color value won't accept a string or a tuple of RGB values; it wants a QColor object. A method that returns a size won't return a (width, height) tuple; it will return a

QSize object. PyQt mitigates this somewhat by automatically converting some common data types (for example, strings, lists, dates, and times) between Qt objects and Python standard library types; however, there are many hundreds of Qt classes that have no analog in the Python standard library.

Qt relies heavily on named constants called enums or flags to represent things such as option settings or configuration values. For example, if you wanted to switch the state of a window between minimized, floating, or maximized, you would need to pass the window a constant that is found in the QtCore.Qt.WindowState enum.

Setting or retrieving values on Qt objects requires the use of accessor methods, sometimes known as setter and getter methods, rather than direct access to the properties.

To the Python programmer, Qt can seem to have an almost maniacal obsession with defining classes and constants, and you'll spend a lot of time early on searching the documentation to locate the item you need to configure your objects. Don't despair! You'll soon become acclimated to the Qt way of working.

Understanding Qt's documentation

Qt is such a vast and complex library that no print book could hope to document a significant portion of it in any detail. For that reason, it's important to learn how to access and understand the documentation available online. For Python programmers, this presents a minor challenge.

Qt itself is blessed with detailed and excellent documentation that documents all Qt modules and classes, including example code and high-level tutorials on coding with Qt. However, this documentation is all aimed at C++ development; all example code is in C++, and there is no indication when a methodology or approach to a problem differs for Python.

PyQt's documentation is considerably sparser. It only covers the Python-specific differences and lacks the comprehensive class reference, example code, and tutorials that make Qt's documentation great. It is an essential read for anyone working with PyQt, but it's by no means complete.

With the release of Qt for Python, there is an effort underway to port Qt's C++ documentation to Python at https://doc-snapshots.qt.io/qtforpython/. When finished, this will also be a valuable resource for PyQt programmers. At the time of writing, though, the effort is far from complete; in any case, there are minor differences between PyQt and Qt for Python that may make this documentation as confusing as it is helpful.

If you have a rudimentary knowledge of C++ syntax, it's not too difficult to mentally translate the Qt documentation to Python, though it can be confusing in many cases. One of the aims of this book is to close the gap for those who aren't well-versed in C++.

Core Qt modules

For the first six chapters of this book, we'll be working primarily with three Qt modules:

  • QtCore, which contains low-level data wrapper classes, utility functions, and non-GUI core functionality
  • QtGui, which contains GUI-specific data wrapper classes and utilities
  • QtWidgets, which defines GUI widgets, layouts, and other high-level GUI components

Those three modules will be used in nearly any PyQt program we write. Later in the book, we will explore other modules for graphics, networking, web rendering, multimedia, and other advanced capabilities.

Creating Hello Qt – our first window

Now that you've learned about Qt5 and PyQt5, it's time to dig in and do some coding. Make sure everything is installed, open your favorite Python editor or IDE, and let's begin!

Create a hello_world.py file in your editor, and enter the following:

from PyQt5 import QtWidgets

We begin by importing the QtWidgets module. This module contains the bulk of the widget classes in Qt, as well as some other important components for GUI creation. We won't need QtGui or QtCore for such a simple application.

Next, we need to create a QApplication object, like this:

app = QtWidgets.QApplication([])

The QApplication object represents the state of our running application, and one must be created before any other Qt widgets can be created. QApplication is supposed to be

passed a list of command-line arguments given to our script, but here we're just passing in an empty list.

Now, let's create our first widget:

window = QtWidgets.QWidget(windowTitle='Hello Qt')

In GUI toolkit terms, a widget refers to the visible components of the GUI, such as buttons, labels, text entries, or blank panels. The most generic widget in Qt is the QWidget object, which is just a blank window or panel. As we create this widget, we're settings its windowTitle to 'Hello Qt'. windowTitle is what is known as property. All Qt objects

and widgets have properties, which are used to configure different aspects of the widget. In this case, windowTitle is the name of the program window and appears in the window decorations, on the taskbar or dock, or wherever else your OS and desktop environment choose to use it.

Unlike most Python libraries, Qt properties and methods are named using camelCase rather than snake_case.

The properties available for configuring a Qt object can be set by passing them as constructor arguments or using the appropriate setter method. Typically, this is just set plus the name of the property, so we could have written this:

window = QtWidgets.QWidget() window.setWindowTitle('Hello Qt')

Properties can also be retrieved using the getter method, which is just the property name:

print(window.windowTitle()) Once a widget is created, we can make it appear by calling show(), as follows:

window.show()

Calling show() automatically makes window a top-level window of its own. In Chapter

2, Building Forms with Qt Widgets, you'll see how to place widgets inside other widgets, but, for this program, we only need one top-level widget.

The last line is a call to app.exec(), like this:

app.exec()

app.exec() begins the QApplication object event loop. The event loop will run forever until the application quits, processing our user interactions with the GUI. Note that the app object never refers to window, nor window to the app object. These objects are connected automatically in the background; you need only ensure that a QApplication object exists before creating any QWidget objects.

Save the hello_world.py file and run the script from your editor, or from a command line, like so:

python hello_world.py When you run this, you should see a blank window whose title text is Hello Qt:

This isn't a terribly exciting application, but it does show us the basic workflow of any PyQt application:

  1. Create a QApplication object
  2. Create our main application window
  3. Display our main application window
  4. Call QApplication.exec() to start the event loop

If you're experimenting with PyQt in the Python Read-Eval-Print- Loop (REPL), create the QApplication object by passing in a list with a single empty string, like this: QtWidgets.QApplication(['']);

otherwise, Qt will crash. Also, you don't need to call QApplication.exec() in the REPL, thanks to some special PyQt magic.

Creating a PyQt application template

hello_world.py demonstrated the bare minimum of code to get a Qt window on the

screen, but it's a bit too simplistic to serve as a model for more complex applications. In this book, we're going to be creating many PyQt applications, so, to make things easier, we're going to compose a basic application template. Future chapters will refer to this template, so make sure to create it exactly as specified.

Open a new file called qt_template.py, and add in these imports:

import sys

from PyQt5 import QtWidgets as qtw from PyQt5 import QtGui as qtg

from PyQt5 import QtCore as qtc

We'll start with importing sys, so that we can pass QApplication an actual list of script arguments; then we'll import our three main Qt modules. To save some typing, while avoiding star imports, we're going to alias them to abbreviated names. We'll be using these aliases consistently throughout the book as well.

Star imports (also called wildcard imports), such as from

PyQt5.QtWidgets import *, are convenient and often seen in tutorials, but, in practice, they are best avoided. Doing this with a PyQt module will fill your namespace with hundreds of classes, functions, and constants, any of which you might accidentally overwrite with a variable name. Avoiding star imports will also help you to learn which modules contain which commonly used classes.

Next, we'll create a MainWindow class, as follows:

class MainWindow(qtw.QWidget):

def __init__(self):

"""MainWindow constructor""" super().__init__()

  • Main UI code goes here
  • End main UI code

self.show()

To make our MainWindow class, we subclass QWidget, then override the constructor

method. Whenever we use this template in future chapters, start adding your code between the commented lines unless otherwise instructed.

Subclassing PyQt classes is a good way to approach GUI building. It allows us to customize and expand on Qt's powerful widget classes without having to reinvent the wheel. In many cases, subclassing is the only way to utilize certain classes or accomplish certain customizations.

Our constructor ends with a call to self.show(), so our MainWindow will take care of showing itself.

Always remember to call super().__init__() inside your child class's constructor, especially with Qt classes. Failing to do so means the parent class isn't properly set up and will undoubtedly cause very frustrating bugs.

We'll finish our template with the main code execution:

if __name__ == '__main__':

app = qtw.QApplication(sys.argv) mw = MainWindow() sys.exit(app.exec())

In this code, we're going to create our QApplication object, make our MainWindow object, and then call QApplication.exec(). Although not strictly necessary, it's best practice to create the QApplication object at the global scope (outside of any function or class). This ensures that all Qt objects get properly closed and cleaned up when the application quits.

Notice that we're passing sys.argv into QApplication(); Qt has several default command-line arguments that can be used for debugging or to alter styles and themes. These are processed by the QApplication constructor if you pass in sys.argv.

Also, note that we're calling app.exec() inside a call to sys.exit; this is a small touch that causes the exit code of app.exec() to be passed to sys.exit(), so we pass appropriate exit codes to the OS, if the underlying Qt instance crashes for some reason.

Finally, note that we've wrapped this block in this check:

if __name__ == '__main__':

If you've never seen this before, it's a common Python idiom that simply means: only run this code if this script is called directly. By putting our main execution in this block, we could conceivably import this file into another Python script and be able to reuse our MainWindow class without running any of the code in this block.

If you run your template code, you should see a blank application window. In the following chapters, we'll be filling that window with various widgets and functionality.

Introducing Qt Designer

Before we wrap up our introduction to Qt, let's look at a free tool offered by the Qt company that can help us create PyQt applications—Qt Designer.

Qt Designer is a graphical WYSIWYG GUI designer for Qt. Using Qt Designer, you can drag and drop GUI components into an application and configure them without having to write any code at all. While it is certainly an optional tool, you may find it useful for prototyping, or preferable to hand-coding a large and complex GUI. While most of the code in this book will be hand-coded, we will be covering the use of Qt Designer with PyQt in Chapter 2, Building Forms with Qt Widgets, and Chapter 3, *Handling Events with Signals and

Slots.

Using Qt Designer

Let's take a moment to get familiar with how to launch and use Qt Designer:

  1. Launch Qt Creator
  2. Select File | New File or Project
  3. Under Files and Classes, select Qt
  4. Choose Qt Designer Form
  5. Under Choose a Template Form, select Widget, then click Next
  6. Give your form a name and click Next
  7. Click Finish

You should see something that looks like this:

If you installed Qt Designer as a standalone application on Linux, launch it with the designer command or select it from your program's menu.

You shouldn't need the previous steps.

Take a few minutes to test out Qt Designer:

  • Drag some widgets from the left pane onto your base widget
  • Resize the widgets if you wish, or select one and examine its properties in the lower-right pane
  • When you've made several changes, select Tools | Form Editor | Preview, or hit Alt + Shift + R, to preview your GUI

In Chapter 2, Building Forms with Qt Widgets, we'll go into detail on how to use Qt Designer to build a GUI interface; for now, you can find out more information about Qt Designer from the manual at https://doc.qt.io/qt-5/qtdesigner-manual.html.

Summary

In this chapter, you learned about the Qt application framework and the PyQt Python bindings for Qt. We wrote a Hello World application and created a template for building larger Qt applications. Finally, we installed and took our first look at Qt Designer, the GUI editor.

In Chapter 2, Building Forms with Qt Widgets, we'll get familiar with some of the basic Qt widgets and learn how to resize and arrange them in a user interface. You'll then apply that knowledge by designing a calendar application in both code and Qt Designer.

Questions

Try these questions to test your knowledge from this chapter:

  1. Qt is written in C++, a language that is very different from Python. What are some of the major differences between the two languages? How might these differences come across as we use Qt in Python?
  2. GUIs are composed of widgets. Open some GUI applications on your computer and try to identify as many widgets as you can.
  3. The following program crashes. Figure out why, and fix it so that it shows a window:

from PyQt5.QtWidgets import *

app = QWidget() app.show() QApplication().exec()

  1. The QWidget class has a property called statusTip. Which of these are most likely to be the names of the accessor methods for this property?
  2. getStatusTip() and setStatusTip()
  3. statusTip() and setStatusTip()
  4. get_statusTip() and change_statusTip()
  5. QDate is a class for wrapping a calendar date. In which of the three main Qt modules would you expect to find it?
  6. QFont is a class that defines a screen font. In which of the three main Qt modules would you expect to find it?
  7. Can you recreate hello_world.py using Qt Designer? Make sure to set the windowTitle.

Further reading

Check out these resources for more information on Qt, PyQt, and Qt Designer:

[ 24 ] )

'Mastering-GUI-Programming' 카테고리의 다른 글

Styling Qt Applications  (0) 2023.03.08
Building Applications with QMainWindow  (0) 2023.03.08
Handling Events with Signals and Slots  (0) 2023.03.08
Building Forms with QtWidgets  (0) 2023.03.08

댓글