PyQt6,用 Python 开发高级 GUI
Python 凭借其简洁易用和庞大的生态系统,已成为各领域开发人员的首选语言。在创建桌面应用程序方面,Qt6 无疑是一款强大的工具包。Qt6 是 Qt 框架的最新版本,相比前代产品,它提供了增强的特性和功能,使其成为构建跨平台 GUI 应用程序的首选。
Qt6 的设计理念是更加模块化、高效和适应性。它在图形处理、性能和易用性方面进行了改进,确保开发人员拥有一个强大的应用程序框架。借助 PyQt6 或 PySide6 绑定,Python 与 Qt6 的集成将 Python 的易脚本编写能力与 Qt 丰富的 GUI 功能完美结合。
今天就跟云朵君一起学习 PyQt6 吧~
设置开发环境
要开始使用 Python 开发 Qt6 应用程序,你需要设置开发环境。这包括安装 Python 和 Qt6 绑定。PyQt6 和 PySide6 是 Python 的两个主要绑定。
安装 Python:从官方网站下载并安装最新版本的 Python。确保将 Python 添加到系统的 PATH 中。 安装PyQt6或PySide6:
PyQt6:你可以使用 pip 安装 PyQt6:
pip install PyQt6
PySide6:同样,对于 PySide6:
pip install PySide6
Qt Designer:为了直观地设计你的应用程序,你可能需要安装 Qt Designer,它包含在 Qt 工具包中。你也可以通过 pip 安装它:
pip install PyQt6-tools # 对于 PyQt6
pip install pyside6-tools # 对于 PySide6
基本小部件
QPushButton
QPushButton是一个可点击的按钮,用于执行操作或回答问题。
from PyQt6.QtWidgets import QApplication, QPushButton, QWidget, QVBoxLayout
defon_click():
print ( '按钮被点击!' )
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
button = QPushButton( '点击我' )
button.clicked.connect(on_click) # 将信号连接到插槽
layout.addWidget(button)
window.setLayout(layout)
window.show()
app. exec ()
QLabel
QLabel显示文本或图像。它通常用于指示表单字段、提供提示或显示图像。
from PyQt6.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
label = QLabel( 'Hello, PyQt6!' )
layout.addWidget(label)
window.setLayout(layout)
window.show()
app.exec ( )
布局管理
QVBoxLayout 和 QHBoxLayout
QVBoxLayout 和 QHBoxLayout用于垂直和水平排列小部件。
from PyQt6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QHBoxLayout, QWidget
app = QApplication([])
window = QWidget()
v_layout = QVBoxLayout()
h_layout = QHBoxLayout()
btn1 = QPushButton('按钮 1')
btn2 = QPushButton('按钮 2')
v_layout.addWidget(btn1)
h_layout.addWidget(btn2)
window.setLayout(v_layout)
window.setLayout(h_layout)
window.show()
app.exec()
对话框
QMessageBox
QMessageBox用于显示消息。
from PyQt6.QtWidgets import QApplication, QMessageBox
app = QApplication([])
msg_box = QMessageBox()
msg_box.setText( "这是一个消息框。" )
msg_box.exec ( )
高级小部件
QTableView
QTableView提供使用模型来管理数据的表格视图。
from PyQt6.QtWidgets import QApplication, QTableView, QWidget, QVBoxLayout
from PyQt6.QtCore import QAbstractTableModel, Qt
classMyTableModel(QAbstractTableModel):
defrowCount(self,parent):
return 5 # 示例行数
defcolumnCount(self,parent):
return 3 # 示例列数
defdata(self,index,role):
ifrole == Qt.ItemDataRole.DisplayRole:
returnf"Cell ({index.row()},{index.column()})"
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
table_view = QTableView()
model = MyTableModel()
table_view.setModel(model)
layout.addWidget(table_view)
window.setLayout(layout)
window.show()
app.exec()
图形视图框架
QGraphicsView 和 QGraphicsScene
QGraphicsView是一个提供QGraphicsScene可视化表示的小部件。它用于复杂的图形和自定义项目。
from PyQt6.QtWidgets import QApplication, QGraphicsScene, QGraphicsView
app = QApplication([])
scene = QGraphicsScene()
scene.addText("Hello, PyQt6 Graphics View!")
view = QGraphicsView(scene)
view.show()
app.exec()
自定义小部件
创建自定义小部件涉及从现有小部件或直接从现有小部件进行QWidget子类化,然后覆盖方法来定制行为和外观。
from PyQt6.QtWidgets import QApplication, QWidget, QPainter, QBrush, QPen
from PyQt6.QtCore import Qt
classCustomWidget(QWidget):
defpaintEvent(self, event):
painter = QPainter(self)
painter.setPen(QPen(Qt.blue, 8, Qt.SolidLine))
painter.setBrush(QBrush(Qt.green, Qt.SolidPattern))
painter.drawRect(10, 10, 200, 200)
app = QApplication([])
custom_widget = CustomWidget()
custom_widget.show()
app.exec()
输入小部件
QLineEdit
QLineEdit小部件允许用户输入和编辑单行纯文本。
from PyQt6.QtWidgets import QApplication, QLineEdit, QWidget, QVBoxLayout
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
line_edit = QLineEdit()
line_edit.setPlaceholderText( "输入一些文本..." )
layout.addWidget(line_edit)
window.setLayout(layout)
window.show()
app.exec ()
QTextEdit
QTextEdit提供了一个用于编辑和显示纯文本和富文本的小部件。
from PyQt6.QtWidgets import QApplication, QTextEdit, QWidget, QVBoxLayout
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
text_edit = QTextEdit()
text_edit.setPlainText( "这是一个 QTextEdit 小部件。您可以编辑我!" )
layout.addWidget(text_edit)
window.setLayout(layout)
window.show()
app. exec ()
选择小部件
QComboBox
QComboBox是一个小部件,允许用户从选项列表中选择或输入自己的选项。
from PyQt6.QtWidgets import QApplication, QComboBox, QWidget, QVBoxLayout
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
combo_box = QComboBox()
combo_box.addItems(["选项 1", "选项 2" , "选项 3"])
layout.addWidget(combo_box)
window.setLayout(layout)
window.show()
app.exec()
QSpinBox 和 QDoubleSpinBox
QSpinBox和QDoubleSpinBox是分别允许用户从整数或浮点值范围中进行选择的小部件。
from PyQt6.QtWidgets import QApplication, QSpinBox, QDoubleSpinBox, QWidget, QVBoxLayout
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
spin_box = QSpinBox()
spin_box.setRange(0, 100)
layout.addWidget(spin_box)
double_spin_box = QDoubleSpinBox()
double_spin_box.setRange(0.0, 100.0)
layout.addWidget(double_spin_box)
window.setLayout(layout)
window.show()
app.exec()
控制部件
QSlider
QSlider是一个控制小部件,允许用户通过滑动手柄从线性范围中选择一个值。
from PyQt6.QtWidgets import QApplication, QSlider, QWidget, QVBoxLayout
from PyQt6.QtCore import Qt
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
slider = QSlider(Qt.Orientation.Horizontal)
slider.setRange(0 , 100 )
layout.addWidget(slider)
window.setLayout(layout)
window.show()
app.exec()
QDial
QDial 与 QSlider 类似,但提供圆形拨号界面。
from PyQt6.QtWidgets import QApplication, QDial, QWidget, QVBoxLayout
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
dial = QDial()
dial.setRange(0 , 100)
layout.addWidget(dial)
window.setLayout(layout)
window.show()
app.exec()
显示小部件
QProgressBar
QProgressBar提供水平或垂直进度条。
from PyQt6.QtWidgets import QApplication, QProgressBar, QWidget, QVBoxLayout
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
progress_bar = QProgressBar()
progress_bar.setRange( 0 , 100 )
progress_bar.setValue( 75 )
layout.addWidget(progress_bar)
window.setLayout(layout)
window.show()
app.exec ( )
QLCD编号
QLCDNumber以类似 LCD 的风格显示数字。
from PyQt6.QtWidgets import QApplication, QLCDNumber, QWidget, QVBoxLayout
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
lcd_number = QLCDNumber()
lcd_number.display(123)
layout.addWidget(lcd_number)
window.setLayout(layout)
window.show()
app.exec()
创建第一个 Qt6 应用程序
下面就和云朵君一起开始创建一个简单的 Qt6 应用程序,它会打开一个带有问候消息的窗口。此示例使用 PyQt6,但你可以通过更改 import 语句轻松地将其适配到 PySide6。
import sys
from PyQt6.QtWidgets import QApplication, QLabel, QWidget
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle('Hello Qt6')
label = QLabel('Welcome to Qt6 with Python', window)
window.setGeometry(100, 100, 280, 80)
label.move(50, 20)
window.show()
sys.exit(app.exec())
探索 Qt6 GUI 元素
小部件
小部件是 Qt6 应用程序的基石。从简单的标签到复杂的滑块,Qt6 提供了丰富的小部件。以下是创建 QPushButton 的方法:
from PyQt6.QtWidgets import QApplication, QPushButton
app = QApplication([])
button = QPushButton('Click Me')
button.clicked.connect(lambda: print('Button clicked!'))
button.show()
app.exec()
布局
布局有助于组织窗口内的小部件。Qt6 提供了多种布局,例如 QHBoxLayout、QVBoxLayout 和 GridLayout。以下是使用 QVBoxLayout 的示例:
from PyQt6.QtWidgets import QApplication, QVBoxLayout, QWidget, QPushButton
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
layout.addWidget(QPushButton('按钮 1'))
layout.addWidget(QPushButton('按钮 2'))
window.setLayout(layout)
window.show()
app.exec ( )
对话框和窗口
对话框是用于用户交互的特殊窗口。在 Qt6 中创建对话框非常简单:
from PyQt6.QtWidgets import QApplication, QDialog, QDialogButtonBox, QVBoxLayout
app = QApplication([])
dialog = QDialog()
buttonBox = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
buttonBox.accepted.connect(dialog.accept)
buttonBox.rejected.connect(dialog.reject)
layout = QVBoxLayout()
layout.addWidget(buttonBox)
dialog.setLayout(layout)
dialog.exec()
高级 Qt6 功能
图形和自定义小部件
Qt6 增强了对图形的支持,允许创建自定义小部件和复杂的图形元素。以下是绘制简单矩形的代码片段:
from PyQt6.QtWidgets import QApplication, QWidget
from PyQt6.QtGui import QPainter, QColor
from PyQt6.QtCore import Qt
classMyWidget(QWidget):
defpaintEvent(self, event):
painter = QPainter(self)
painter.setBrush(QColor(255, 0, 0, 180))
painter.drawRect(10, 10, 100, 100)
app = QApplication([])
myWidget = MyWidget()
myWidget.show()
app.exec()
数据库集成
Qt6 提供了强大的数据库集成支持,可以轻松连接到主流数据库。以下是连接到 SQLite 数据库的方法:
from PyQt6.QtSql import QSqlDatabase, QSqlQuery
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(":memory:")
if db.open():
query = QSqlQuery()
query.exec("CREATE TABLE people (id INTEGER PRIMARY KEY, name TEXT)")
Qt6 中的多线程
Qt6 支持多线程,这对于在执行长时间操作时保持 UI 的响应至关重要。以下是使用 QThread 的示例:
from PyQt6.QtCore import QThread, pyqtSignal
from PyQt6.QtWidgets import QApplication, QLabel
classWorker(QThread):
updated = pyqtSignal(str)
defrun(self):
# Long running task
self.updated.emit("Task Finished")
app = QApplication([])
label = QLabel("Starting...")
label.show()
worker = Worker()
worker.updated.connect(lambda text: label.setText(text))
worker.start()
app.exec()
高级 PyQt6 概念
PyQt6 的高级概念可用于创建更复杂、交互性更强的 GUI 应用程序。以下是一些高级主题的讲解和代码示例,包括模型-视图-控制器 (MVC) 架构、自定义控件、图形视图框架以及 PyQt6 中的线程处理。
1. 模型-视图-控制器(MVC)架构
MVC 架构将数据模型、用户界面和控制逻辑分离到不同的组件中。这种分离使得应用程序更易于维护和扩展。
示例:为列表编辑器应用程序实现简单的 MVC。
from PyQt6.QtWidgets import QApplication, QMainWindow, QListWidget, QVBoxLayout, QWidget, QPushButton
classModel:
def__init__(self, data):
self.data = data
classView(QMainWindow):
def__init__(self, model):
super().__init__()
self.model = model
self.initUI()
definitUI(self):
self.setWindowTitle('MVC Example')
self.listWidget = QListWidget()
for entry in self.model.data:
self.listWidget.addItem(entry)
self.addButton = QPushButton("Add Item")
self.layout = QVBoxLayout()
self.layout.addWidget(self.listWidget)
self.layout.addWidget(self.addButton)
self.container = QWidget()
self.container.setLayout(self.layout)
self.setCentralWidget(self.container)
classController:
def__init__(self, model, view):
self.model = model
self.view = view
self.connectSignals()
defconnectSignals(self):
self.view.addButton.clicked.connect(self.addItem)
defaddItem(self):
itemText = f"Item {len(self.model.data) + 1}"
self.model.data.append(itemText)
self.view.listWidget.addItem(itemText)
if __name__ == '__main__':
app = QApplication([])
model = Model(['Item 1', 'Item 2', 'Item 3'])
view = View(model)
controller = Controller(model, view)
view.show()
app.exec()
2. 自定义小部件
创建自定义小部件涉及对现有的 PyQt6 小部件或基QWidget类进行子类化,然后重写方法来自定义小部件的外观和行为。
示例:创建自定义按钮小部件。
from PyQt6.QtWidgets import QPushButton, QApplication, QWidget, QVBoxLayout
from PyQt6.QtGui import QPainter, QColor
from PyQt6.QtCore import Qt
classColorButton(QPushButton):
def__init__(self, color, parent=None):
super().__init__(parent)
self.color = color
defpaintEvent(self, event):
painter = QPainter(self)
painter.setBrush(QColor(self.color))
painter.drawRect(self.rect())
if __name__ == '__main__':
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
redButton = ColorButton('red')
greenButton = ColorButton('green')
layout.addWidget(redButton)
layout.addWidget(greenButton)
window.setLayout(layout)
window.show()
app.exec()
3. 图形视图框架
图形视图框架提供了基于场景的画布,用于管理和与大量自定义 2D 图形项目进行交互。
示例:在场景中显示自定义项目。
from PyQt6.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsEllipseItem
from PyQt6.QtCore import Qt
classGraphicsExample(QGraphicsView):
def__init__(self):
super().__init__()
self.scene = QGraphicsScene()
self.setScene(self.scene)
self.initUI()
definitUI(self):
ellipse = QGraphicsEllipseItem(0, 0, 100, 50)
self.scene.addItem(ellipse)
if __name__ == '__main__':
app = QApplication([])
view = GraphicsExample()
view.show()
app.exec()
4. PyQt6 中的线程
对于长时间运行的操作,将工作负载移至单独的线程可防止 GUI 卡死。PyQt6 不仅集成了 Python 的线程模块,还提供了自己的QThread线程管理类。
示例:QThread用于后台任务。
from PyQt6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
from PyQt6.QtCore import QThread, pyqtSignal
import time
classWorker(QThread):
finished = pyqtSignal()
defrun(self):
time.sleep(5) # Simulate a long-running task
self.finished.emit()
classMainWindow(QWidget):
def__init__(self):
super().__init__()
self.button = QPushButton("Start Task")
self.button.clicked.connect(self.startTask)
layout = QVBoxLayout()
layout.addWidget(self.button)
self.setLayout(layout)
defstartTask(self):
self.thread = Worker()
self.thread.finished.connect(self.taskFinished)
self.thread.start()
deftaskFinished(self):
self.button.setText("Task Finished")
if __name__ == '__main__':
app = QApplication([])
window = MainWindow()
window.show()
app.exec()
这些示例展示了 PyQt6 在开发复杂应用程序方面的多功能性和强大功能。通过利用这些先进的概念,开发人员可以创建兼具功能性和视觉吸引力的应用程序。
简单计算器示例
创建一个简单的计算器是熟悉 PyQt6 的好方法,它可以演示如何与小部件交互、处理事件以及执行基本操作。以下是创建可执行加、减、乘、除运算的基本计算器的分步指南。
步骤1:导入PyQt6模块
首先,你需要从 PyQt6 导入必要的模块。
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QLineEdit
import sys
步骤 2:创建计算器的 GUI
为计算器的 GUI 定义一个类。该类将创建计算器窗口、布局、显示区域(用于显示计算结果或输入)以及用于数字和运算的按钮。
classSimpleCalculator(QWidget):
def__init__(self):
super ().__init__()
self.setWindowTitle("Simple Calculator")
self.create_ui()
defcreate_ui(self):
# 创建垂直布局
self.layout = QVBoxLayout()
# 创建显示行编辑
self.display = QLineEdit()
# 使显示只读
self.display.setReadOnly( True )
self.layout.addWidget(self.display)
self.create_buttons()
self.setLayout(self.layout)
defcreate_buttons(self):
# 计算器的按钮
buttons = [
'7' , '8' , '9' , '/' ,
'4' , '5' , '6' , '*'
, ' 1' , '2' , ' 3' , '-' ,
'0' , '.' , '=' , '+'
]
# 创建按钮并将其添加到布局
for button in buttons:
btn = QPushButton(button)
btn.clicked.connect(self.on_click)
self.layout.addWidget(btn)
defon_click(self):
# 获取被点击的按钮
button = self.sender()
# 获取按钮的文本
text = button.text()
if text == "=" :
# 如果按下了等于按钮,则评估表达式
try :
result = str(eval (self.display.text()))
self.display.setText(result)
except Exception as e:
self.display.setText("Error")
else :
# 如果按下了任何其他按钮,则将其文本添加到显示
self.display.setText(self.display.text() + text)
步骤3:初始化并显示计算器
定义SimpleCalculator类之后,你需要在启动应用程序的主循环之前创建一个QApplication实例和计算器。
if __name__ == "__main__":
app = QApplication(sys.argv)
calculator = SimpleCalculator()
calculator.show()
sys.exit(app.exec())
这个简单的计算器允许用户使用按钮输入基本的算术运算,并在点击“=”按钮时显示结果。eval函数用于计算显示中的字符串表达式,这是一种简单但可能不安全的执行动态表达式的方法。对于实际应用,请考虑实现更安全的计算机制,以避免eval相关的风险。
此示例涵盖了基本操作,并为构建更复杂的功能(例如处理更复杂的数学运算、改进错误处理和增强用户界面)提供了基础。
设计原则和最佳实践
使用 Qt6 和 Python 进行开发时,请考虑以下最佳实践:
模块化设计:将代码组织成模块和类。 信号和槽机制:利用Qt的信号和槽机制进行对象之间的通信。 资源管理:注意资源管理,尤其是图形和数据库连接。 用户体验:关注用户体验,确保你的应用程序直观且响应迅速。
真实世界的应用示例
VLC 媒体播放器、Calibre 和 Anki 是 Qt6 多功能性的典型代表。分析这些应用程序会发现一些共同的挑战,例如处理多媒体内容、管理庞大的库以及实现间隔重复算法。
写在最后
Python 和 Qt6 为开发跨平台桌面应用程序提供了强大的组合。利用 Python 的简洁性和 Qt6 全面的 GUI 元素,开发人员可以相对轻松地创建复杂的应用程序。
Qt6 丰富的 GUI 元素,加上 Python 的简洁易读性,确保开发者能够高效地设计出不仅视觉上赏心悦目,而且功能强大、响应迅速的界面。丰富的小部件、强大的事件处理以及信号和槽机制,助力创建出在当今软件领域脱颖而出的交互式、用户友好的应用程序。