在本教程中,我们将学习如何使用PySide使用Python创建桌面应用程序。首先,我们将在桌面上创建一系列简单的窗口,以确保PySide正常工作,并介绍一些基本概念。然后,我们将简要介绍事件循环及其与Python中GUI编程的关系。最后,我们将看看Qt的QMainWindow,它提供了一些有用的通用界面元素,如工具栏和菜单。这些将在后续教程中详细介绍。
Creating an application
让我们创建第一个应用程序!要开始创建一个新的Python文件,您可以随意调用它(例如app.py)并将其保存在可访问的地方。我们将在这个文件中编写我们的简单应用程序。
随着时间的推移,我们将在此文件中进行编辑,您可能希望返回到代码的早期版本,因此请记住定期备份。
应用程序的源代码如下所示。逐字输入,注意不要出错。如果你真的搞砸了,Python会让你知道出了什么问题。
from PySide6.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.
首先,启动应用程序。您可以像其他Python脚本一样从命令行运行它,例如--
python3 app.py
快跑!现在您将看到您的窗口。Qt会自动创建一个带有普通窗口装饰的窗口,您可以拖动它,并像调整任何窗口一样调整大小。
您将看到的内容取决于您运行此示例的平台。下图显示了Windows、macOS和Linux(Ubuntu)上显示的窗口。
Stepping through the code
让我们逐行逐行地浏览代码,这样我们就能准确地理解发生了什么。
首先,我们导入应用程序所需的PySide类。这里我们将从QtWidgets模块导入QApplication、应用程序处理程序和QWidget(一个基本的空GUI小部件)。
from PySide6.QtWidgets import QApplication, QWidget
Qt的主要模块是QtWidgets、QtGui和QtCore。
您可以通过from <module> import *进行导入,但这种全局导入在Python中通常是不受欢迎的,因此我们将在这里避免它。
接下来,我们创建一个QApplication实例,传入sys.arg,它是包含传递给应用程序的命令行参数的Python列表。
app = QApplication(sys.argv)
如果你知道你不会使用命令行参数来控制Qt,你可以改为传递一个空列表,例如
app = QApplication([])
接下来,我们使用变量名window创建QWidget的实例。
window = QWidget()
window.show()
在Qt中,所有顶级小部件都是窗口——也就是说,它们没有父级,也没有嵌套在另一个小部件或布局中。这意味着您可以从技术上使用任何您喜欢的小部件创建窗口。
默认情况下,没有父项的小部件是不可见的。因此,在创建window对象之后,我们必须始终调用.show()使其可见。您可以删除.show()并运行应用程序,但您无法退出它!
window是什么?-保存应用程序的用户界面-每个应用程序至少需要一个(…但可以有更多)-应用程序将(默认情况下)在最后一个窗口关闭时退出
最后,我们调用app.exec_()启动事件循环。
What's the event loop?
在屏幕上显示窗口之前,有几个关键概念要介绍一下Qt世界中应用程序的组织方式。如果您已经熟悉事件循环,可以安全地跳到下一节。
每个Qt应用程序的核心是QApplication类。每个应用程序都需要一个并且只有一个QApplication对象才能运行。这个对象保存应用程序的事件循环——控制所有用户与GUI交互的核心循环。
与应用程序的每一次交互——无论是按键、鼠标点击还是鼠标移动——都会生成一个事件,并将其置于事件队列中。在事件循环中,每次迭代都会检查队列,如果发现等待事件,则会将事件和控制传递给事件的特定事件处理程序。事件处理程序处理该事件,然后将控制传递回事件循环以等待更多事件。每个应用程序只有一个正在运行的事件循环。
QApplication类-QApplication保存Qt事件循环-需要一个QApplication实例-您的应用程序在事件循环中等待,直到采取操作-任何时候只有一个事件循环
下划线是因为exec在Python 2.7中是一个保留字。PySide通过在Qt库中使用的名称后面添加下划线来处理这个问题。例如,您还会看到小部件上的.print_()方法。
QMainWindow
正如我们在上一部分中发现的,在Qt中,任何小部件都可以是窗口。例如,如果将QtWidget替换为QPushButton。在下面的示例中,您将得到一个窗口,其中有一个可按下的按钮。
import sys
from PySide6.QtWidgets import QApplication, QPushButton
app = QApplication(sys.argv)
window = QPushButton("Push Me")
window.show()
app.exec_()
这很简单,但不是很有用——很少需要一个仅由单个控件组成的UI!但是,正如我们稍后将要发现的,使用布局将小部件嵌套在其他小部件中的能力意味着您可以在空的QWidget中构建复杂的UI。
但是,Qt已经为您提供了一个解决方案——QMainWindow。这是一个预先制作的小部件,它提供了许多标准窗口功能,您可以在应用程序中使用,包括工具栏、菜单、状态栏、可停靠小部件等。我们稍后将介绍这些高级特性,但现在,我们将向应用程序添加一个简单的空QMainWindow。
import sys
from PySide6.QtWidgets import QApplication, QMainWindow
app = QApplication(sys.argv)
window = QMainWindow()
window.show()
# Start the event loop.
app.exec_()
快跑!现在您将看到主窗口。它看起来和以前完全一样!
因此,我们的QMainWindow目前不是很有趣。我们可以通过添加一些内容来解决这个问题。如果要创建自定义窗口,最好的方法是子类化QMainWindow,然后在__init__块中包含该窗口的设置。这允许窗口行为是自包含的。我们可以添加自己的QMainWindow子类-称其为MainWindow-以保持简单。
import sys
from PySide6.QtCore import QSize, Qt
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton
# Subclass QMainWindow to customize your application's main window
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("My App")
button = QPushButton("Press Me!")
# Set the central widget of the Window.
self.setCentralWidget(button)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
对于这个演示,我们使用QPushButton。核心Qt小部件总是从QtWidgets命名空间导入,QMainWindow和QApplication类也是如此。当使用QMainWindow时,我们使用.setCentralWidget将一个小部件(这里是一个QPushButton)放在QMainWindow中——默认情况下,它占据整个窗口。我们将在布局教程中学习如何向窗口添加多个小部件。
当您子类化Qt类时,必须始终调用super__init__函数以允许Qt设置对象。
在__init__块中,我们首先使用.setWindowTitle()来更改主窗口的标题。然后,我们将第一个小部件QPushButton添加到窗口的中间。这是Qt中可用的基本小部件之一。创建按钮时,可以传递希望按钮显示的文本。
最后,我们在窗口上调用.setCentralWidget()。这是一个特定于QMainWindow的函数,允许您设置窗口中间的小部件。
快跑!现在,您将再次看到窗口,但这次QPushButton小部件位于中间。按下按钮不会有任何作用,接下来我们将对此进行排序。
我们将很快详细介绍更多的小部件,但如果您不耐烦,想继续前进,您可以查看QWidget文档。尝试将不同的小部件添加到窗口中!
Sizing windows and widgets
该窗口目前可以自由调整大小——如果你用鼠标抓住任何角落,你可以将其拖动并调整到你想要的任何大小。虽然允许用户调整应用程序的大小是很好的,但有时您可能希望对最小或最大大小设置限制,或者将窗口锁定为固定大小。
在Qt中,使用QSize对象定义尺寸。这将按该顺序接受宽度和高度参数。例如,下面将创建一个400x300像素的固定大小窗口。
import sys
from PySide6.QtCore import QSize, Qt
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton
# Subclass QMainWindow to customize your application's main window
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("My App")
button = QPushButton("Press Me!")
self.setFixedSize(QSize(400, 300))
# Set the central widget of the Window.
self.setCentralWidget(button)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
快跑!你会看到一个固定大小的窗口——试着调整它的大小,它不会起作用。
控件在Windows和Linux上被禁用。在macOS上,您可以最大化应用程序以填充屏幕,但中央控件不会调整大小。
除了.setFixedSize(),您还可以调用.setMinimumSize(()和.setMaximumSize()分别设置最小和最大大小。你自己试试吧!
您可以在任何小部件上使用这些大小方法。
在本节中,我们介绍了QApplication类、QMainWindow类、事件循环,并尝试向窗口添加一个简单的小部件。在下一节中,我们将了解Qt为小部件和窗口提供的相互通信机制以及您自己的代码。