Create GUI Applications with Python Qt6 (Version 1.0, 2021-05-14, PyQt6) (Martin Fitzpatrick) (z-library.sk, 1lib.sk, z-lib.sk) (1)
PythonAuthor:Martin Fitzpatrick
No description
Tags
Support Statistics
¥.00 ·
0times
Text Preview (First 20 pages)
Registered users can read the full content for free
Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.
Page
1
(This page has no text content)
Page
2
Create GUI Applications with Python & Qt6 The hands-on guide to making apps with Python Martin Fitzpatrick Version 1.0, 2021-05-14
Page
3
Table of Contents Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1. A very brief history of the GUI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2. A bit about Qt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 3. Thank you . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 4. Copyright . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Basic PyQt6 Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 5. My first Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 6. Signals & Slots. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 7. Widgets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 8. Layouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 9. Actions, Toolbars & Menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 10. Dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 11. Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 12. Events. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 Qt Designer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 13. Installing Qt Designer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 14. Getting started with Qt Designer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Theming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 15. Styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 16. Palettes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 17. Icons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 18. Qt Style Sheets (QSS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 Model View Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 19. The Model View Architecture — Model View Controller . . . . . . . . . . . . . . . 262 20. A simple Model View — a Todo List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 21. Tabular data in ModelViews, with numpy & pandas . . . . . . . . . . . . . . . . . . . 283 22. Querying SQL databases with Qt models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308 Further PyQt6 Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341 23. Extending Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342 24. Routing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354 25. Working with command-line arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360 26. System tray & macOS menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
Page
4
27. Enums & the Qt Namespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376 Custom Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387 28. Bitmap Graphics in Qt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 29. Creating Custom Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420 Concurrent Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458 30. Introduction to Threads & Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459 31. Using the thread pool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466 32. Threading examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475 33. Running external commands & processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541 Plotting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551 34. Plotting with PyQtGraph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 552 35. Plotting with Matplotlib. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573 Appendix A: Installing PyQt6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 590 Appendix B: Translating C++ Examples to Python. . . . . . . . . . . . . . . . . . . . . . . . . . . 593 Appendix C: PyQt6 and PySide6 — What’s the difference? . . . . . . . . . . . . . . . . . . . 605 Appendix D: What next?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 619 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 620
Page
5
Introduction If you want to create GUI applications with Python it can be tricky to know where to start. There are a lot of new concepts you need to understand to get anything to work. But, like any coding problem, the first step is learning to approach the problem in the right way. In this book I take you right from the basic principles of GUI development to creating your own, fully functional, desktop apps with PyQt6. The first edition of this book was released in 2016. Since then it has been updated 4 times, adding and expanding chapters in response to reader feedback. There are more PyQt resources available now than when I started, but there is still a shortage of in-depth, practical guides to building complete apps. This book fills that gap! The book is formatted as a series of chapters exploring different aspects of PyQt6 in turn. They are arranged to put the simpler chapters toward the beginning, but if you have specific requirements for your project, don’t be afraid to jump around! Each chapter will guide you through learning the fundamental concepts before taking you through a series of coding examples to gradually explore and learn how to apply the ideas yourself. You can download source code and resources for all examples in this book from http://www.learnpyqt.com/d/pyqt6-source.zip It is not possible to give you a complete overview of the Qt system in a book of this size, so there are links to external resources — both on the LearnPyQt.com website and elsewhere. If you find yourself thinking "I wonder if I can do that?" the best thing you can do is put this book down, then go and find out! Just keep regular backups of your code along the way so you always have something to come back to if you royally mess it up. 1
Page
6
Throughout this book there are boxes like this, giving info, tips and warnings. All of them can be safely skipped over if you are in a hurry, but reading them will give you a deeper and more rounded knowledge of the Qt framework. 2
Page
7
1. A very brief history of the GUI The Graphical User Interface has a long and venerable history dating back as far as the 1960s. Stanford’s NLS (oN-Line System) introduced the mouse and windows concepts, first demonstrated publicly in 1968. This was followed by the Xerox PARC Smalltalk system GUI 1973, which is the foundation of most modern general purpose GUIs. These early systems already had many of the features we take for granted in modern desktop GUIs, including windows, menus, radio buttons, check boxes and later icons. This combination of features — gave us the early acronym used for these types of interfaces: WIMP (windows, icons, menus, pointing device — a mouse). In 1979 the first commercial system featuring a GUI was released — the PERQ workstation. This spurred a number of other GUI efforts including notably the Apple Lisa (1983), which added the concept of the menu bar and window controls. As well as many other systems from the Atari ST (GEM), Amiga. On UNIX (and later Linux) the X Window System emerged in 1984. The first version of Windows for PC was released in 1985. Figure 1. The desktop on Microsoft Windows 3.1 (1992) and Apple System 7 (1991) Early GUIs were not the instant hit we might assume, due to the lack of compatible software at launch and expensive hardware 3
Page
8
requirements — particularly for home users. Slowly, but steadily, the GUI interface become the preferred way to interact with computers and the WIMP metaphor became firmly established as the standard. That’s not to say there haven’t been attempts to replace the WIMP metaphor on the desktop. Microsoft Bob (1995), for example, was Microsoft’s much maligned attempt to replace the desktop with a house. Figure 2. Microsoft Bob — Discarding the desktop metaphor for a cartoon house. There have been no shortage of other GUIs hailed as revolutionary in their time, from the launch of Windows 95 (1995) through to Mac OS X (2001), GNOME Shell (2011) and Windows 10 (2015). Each of these overhauled the UIs of their respective desktop systems, often with much fanfare. But fundamentally nothing really changed. These new UIs are still very much WIMP systems and function in exactly the same way as GUIs have since the 1980s. When the revolution came, it was mobile — the mouse has been replaced by touch, and windows by full-screen apps. But even in a world where we all walk around with smartphones in our pocket, a huge amount of daily work is still done on desktop computers. WIMP has survived 40 years of innovation and looks to survive many more. 4
Page
9
2. A bit about Qt Qt is a free and open-source widget toolkit for creating cross-platform GUI applications, allowing applications to target multiple platforms from Windows, macOS, Linux and Android with a single codebase. But Qt is much more than a widget toolkit and features built in support for multimedia, databases, vector graphics and MVC interfaces, it is more accurate to think of it as an application development framework. Qt was started by Eirik Chambe-Eng and Haavard Nord in 1991, founding the first Qt company Trolltech in 1994. Qt is currently developed by The Qt Company and continues to be regularly updated, adding features and extending mobile and cross-platform support. Qt and PyQt6 PyQt6 is a Python binding of the Qt toolkit, developed by Riverbank Computing. When you write applications using PyQt6 what you area really doing is writing applications in Qt. The PyQt6 library is simply. [1] a wrapper around the C++ Qt library, to allow it to be used in Python. Because this is a Python interface to a C++ library the naming conventions used within PyQt6 do not adhere to PEP8 standards. Most notably functions and variables are named using mixedCase rather than snake_case. Whether you adhere to this standard in your own applications is entirely up to you, however I found it helped to follow Python standards for my own code, to help clarify where the PyQt6 code ends and your own begins. Lastly, while there is PyQt6 specific documentation available, you will often find yourself reading the Qt documentation itself as it is more complete. If you need advice on converting Qt C++ code to Python, take a look at Translating C++ Examples to Python. This book is written to work with the latest version of Qt 6. As of writing this is Qt 5
Page
10
6.2. However, many of the examples will work fine with earlier and later versions of Qt. [1] Not really that simple. 6
Page
11
3. Thank you This book continues to be expanded and updated in response to reader feedback. Thankyou to the following readers for their contributions, which helped make this edition what it is! • James Battat, Associate Professor of Physics, Wellesley College • Alex Bender • Andries Broekema • Juan Cabanela • Olivier Girard • Richard Hohlfield • Cody Jackson, Mentor, Code-a-Mom • John E Kadwell • Jeffrey R Kennedy • Gajendra Khanna • Bing Xiao Liu • Alex Lombardi • Juan Pablo Donayre Quintana • Guido Tognan If you have feedback or suggestions for future editions, please get in touch. 7
Page
12
4. Copyright This book is licensed under the Creative Commons Attribution Share-alike Non- commercial license (CC BY-NC-SA) ©2020 Martin Fitzpatrick. • You are free to share unaltered copies of this book with anyone you choose. • If you modify this book and distribute your altered version it must be distributed under the same license. • You are not permitted to sell this book or derivatives in any format. • If you would like to support the author you can legally purchase a copy direct from the author(s). Contributions and corrections from readers (CC BY-NC-SA) are most welcome. 8
Page
13
Basic PyQt6 Features It’s time to take your first steps in creating GUI applications with PyQt6! In this chapter you will be introduced to the basics of PyQt6 that are the foundations of any application you create. We will develop a simple windowed application on your desktop. We’ll add widgets, arrange them using layouts and connect these widgets to functions, allowing you to trigger application behavior from your GUI. Use the provided code as your guide, but always feel free to experiment. That’s the best way to learn how things work. Before you get started, you need a working installation of PyQt6. If you don’t have one yet, check out Installing PyQt6. Don’t forget to download the source code that accompanies this book from http://www.learnpyqt.com/d/pyqt6-source.zip 9
Page
14
5. My first Application Let’s create our first application! To start create a new Python file — you can call it whatever you like (e.g. myapp.py) and save it somewhere accessible. We’ll write our simple app in this file. We’ll be editing within this file as we go along, and you may want to come back to earlier versions of your code, so remember to keep regular backups. Creating your App The source code for your very first application is shown below. Type it in verbatim, and be careful not to make mistakes. If you do mess up, Python will let you know what’s wrong. If you don’t feel like typing it all in, the file is included in the source code with this book. 10
Page
15
Listing 1. basic/creating_a_window_1.py from PyQt6.QtWidgets import QApplication, QWidget # Only needed for access to command line arguments import sys # You need one (and only one) QApplication instance per application. # Pass in sys.argv to allow command line arguments for your app. # If you know you won't use command line arguments QApplication([]) works too. app = QApplication(sys.argv) # Create a Qt widget, which will be our window. window = QWidget() window.show() # IMPORTANT!!!!! Windows are hidden by default. # Start the event loop. app.exec() # Your application won't reach here until you exit and the event # loop has stopped. First, launch your application. You can run it from the command line like any other Python script, for example — python MyApp.py Or, for Python 3 — python3 MyApp.py From now on, you’ll see the following box as a hint to run your application and test it out, along with an indication of what you’ll see. 11
Page
16
Run it! You will now see your window. Qt automatically creates a window with the normal window decorations and you can drag it around and resize it like any window. What you’ll see will depend on what platform you’re running this example on. The image below shows the window as displayed on Windows, macOS and Linux (Ubuntu). Figure 3. Our window, as seen on Windows, macOS and Linux. Stepping through the code Let’s step through the code line by line, so we understand exactly what is happening. First, we import the PyQt6 classes that we need for the application. Here we’re importing QApplication, the application handler and QWidget, a basic empty GUI widget, both from the QtWidgets module. from PyQt6.QtWidgets import QApplication, QWidget The main modules for Qt are QtWidgets, QtGui and QtCore. You could do from <module> import * but this kind of global import is generally frowned upon in Python, so we’ll avoid it here. 12
Page
17
Next we create an instance of QApplication, passing in sys.arg, which is Python list containing the command line arguments passed to the application. app = QApplication(sys.argv) If you know you won’t be using command line arguments to control Qt you can pass in an empty list instead, e.g. app = QApplication([]) Next we create an instance of a QWidget using the variable name window. window = QWidget() window.show() In Qt all top level widgets are windows — that is, they don’t have a parent and are not nested within another widget or layout. This means you can technically create a window using any widget you like. I can’t see my window! Widgets without a parent are invisible by default. So, after creating the window object, we must always call .show() to make it visible. You can remove the .show() and run the app, but you’ll have no way to quit it! What is a window? • Holds the user-interface of your application • Every application needs at least one (…but can have more) • Application will (by default) exit when last window is closed Finally, we call app.exec_() to start up the event loop. 13
Page
18
What’s the event loop? Before getting the window on the screen, there are a few key concepts to introduce about how applications are organised in the Qt world. If you’re already familiar with event loops you can safely skip to the next section. The core of every Qt Applications is the QApplication class. Every application needs one — and only one — QApplication object to function. This object holds the event loop of your application — the core loop which governs all user interaction with the GUI. Figure 4. The event loop in Qt. Each interaction with your application — whether a press of a key, click of a mouse, or mouse movement — generates an event which is placed on the event queue. In the event loop, the queue is checked on each iteration and if a waiting event is found, the event and control is passed to the specific event handler for the event. The event handler deals with the event, then passes control back to the event loop to wait for more events. There is only one running event loop per application. 14
Page
19
The QApplication class • QApplication holds the Qt event loop • One QApplication instance required • You application sits waiting in the event loop until an action is taken • There is only one event loop at any time The underscore is there because exec was a reserved word in Python 2.7. PyQt6 handles this by appending an underscore to the name used in the C++ library. You’ll also see .print_() methods on widgets for example. QMainWindow As we discovered in the last part, in Qt any widgets can be windows. For example, if you replace QtWidget with QPushButton. In the example below, you would get a window with a single push-able button in it. Listing 2. basic/creating_a_window_2.py from PyQt6.QtWidgets import QApplication, QPushButton window = QPushButton("Push Me") window.show() This is neat, but not really very useful — it’s rare that you need a UI that consists of only a single control! But, as we’ll discover later, the ability to nest widgets within other widgets using layouts means you can construct complex UIs inside an empty QWidget. But, Qt already has a solution for you — the QMainWindow. This is a pre-made widget which provides a lot of standard window features you’ll make use of in your apps, including toolbars, menus, a statusbar, dockable widgets and more. We’ll look at these advanced features later, but for now, we’ll add a simple empty QMainWindow to our application. 15
Page
20
Listing 3. basic/creating_a_window_3.py from PyQt6.QtWidgets import QApplication, QMainWindow import sys app = QApplication(sys.argv) window = QMainWindow() window.show() # IMPORTANT!!!!! Windows are hidden by default. # Start the event loop. app.exec() Run it! You will now see your main window. It looks exactly the same as before! So our QMainWindow isn’t very interesting at the moment. We can fix that by adding some content. If you want to create a custom window, the best approach is to subclass QMainWindow and then include the setup for the window in the __init__ block. This allows the window behavior to be self contained. We can add our own subclass of QMainWindow — call it MainWindow to keep things simple. 16
Comments 0
Loading comments...
Reply to Comment
Edit Comment