一、概要
由于作者前期很多年都在使用C++和Qt框架进行项目的开发工作,故可以熟练的使用Qt框架。Qt框架在界面设计以及跨平台运用方面,有着巨大的优势,而界面设计恰恰是python的短板,故使用pyside6实现python和Qt的互补。
1.1 pyside6安装
更新pip工具:
pip install --upgrade pip
命令行执行如下指令:
pip install pyside6 -i https://pypi.doubanio.com/simple
如需在虚拟环境中安装,则执行:
# 创建虚拟环境(例如,Python 3.8)
conda create -n py38 python=3.8
# 激活虚拟环境
conda activate py38
# 安装 PySide6
pip install pyside6 -i https://pypi.doubanio.com/simple
1.2 调用示例
Qt模块和控件的引用:
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QTextEdit
类的创建:
class MainWindow(QMainWindow):
一个完整的示例:
在该示例中,创建了一个MainWindow类,继承自QMainWindow, 并实现了鼠标事件的几个方法。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QTextEdit
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.label = QLabel("Click in this window")
self.setCentralWidget(self.label)
self.setMouseTracking(True)
def mouseMoveEvent(self, e):
self.label.setText("mouseMoveEvent")
def mousePressEvent(self, e):
if e.button() == Qt.LeftButton:
'''点击鼠标左键'''
self.label.setText("鼠标左键被点击")
elif e.button() == Qt.MiddleButton:
'''点击鼠标滚轮'''
self.label.setText("鼠标滚轮被点击")
elif e.button() == Qt.RightButton:
'''点击鼠标右键'''
self.label.setText("鼠标右键被点击")
def mouseReleaseEvent(self, e):
self.label.setText("mouseReleaseEvent")
def mouseDoubleClickEvent(self, e):
self.label.setText("mouseDoubleClickEvent")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.setWindowTitle("这是标题")
window.resize(600,300)
window.show()
sys.exit(app.exec())
二、信号和槽
信号和槽是Qt框架的一个核心亮点,可以在QObject对象中灵活的使用。如果需要使用Qt的信号和槽,从QObject对象继承即可。否则会提示如下的错误:
- 定义 Signal 时会出现 NameError,因为 Signal是在 QObject 中定义的;
- 在 connect() 时会出现 AttributeError,因为 connect() 是 QObject 的成员函数;
- 在 信号emit() 时会出现 AttributeError,即属性错误,因为该类中没有该函数。
2.1 信号和槽定义
由以上内容,我们知道了如何创建和继承自QObject的类,并结合python的特性类定义信号和槽函数。下面提供C++和python定义方式的对比:
C++:
signals:
void startSig();
void endSig();
slots:
void btnStartClicked();
void btnEndClicked();
python:
from PySide6.QtCore import Signal, Slot
...
start_signal = Signal()
end_signal = Signal()
...
@Slot()
def btnStartClicked(self):
pass
@Slot()
def btnEndClicked(self):
pass
2.2 使用示例
主要实现控件已有信号的响应,以及自定义信号和槽的使用。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from PySide6.QtCore import QObject, Signal,Slot
from PySide6.QtWidgets import QApplication,QMainWindow, QHBoxLayout, QVBoxLayout,QWidget, QPushButton,QLabel, QMessageBox
class MainWindow(QMainWindow):
#注意信号的定义位置
customSig = Signal(int, str)
def __init__(self):
super().__init__()
self.cWidget = QWidget()
self.setCentralWidget(self.cWidget)
vLayout = QVBoxLayout()
self.btnStart = QPushButton("start")
vLayout.addWidget(self.btnStart)
self.btnEnd = QPushButton("end")
vLayout.addWidget(self.btnEnd)
self.btnTrigger = QPushButton("trigger")
vLayout.addWidget(self.btnTrigger)
self.cWidget.setLayout(vLayout)
self.setMouseTracking(True)
self.initConnect()
@Slot()
def btnStartClicked(self):
QMessageBox.information(self, '信息提示框', 'Ok btnStartClicked')
@Slot()
def btnEndClicked(self):
QMessageBox.information(self, '信息提示框', 'Ok btnEndlicked')
@Slot()
def btnTriggerClicked(self):
self.customSig.emit(112233,"From custom signal.")
@Slot(int, str)
def customSlot(self,id, msg):
QMessageBox.information(self, '信息提示框', f"id: {id} msg: {msg}")
def initConnect(self):
self.btnStart.clicked.connect(self.btnStartClicked)
self.btnEnd.clicked.connect(self.btnEndClicked)
self.btnTrigger.clicked.connect(self.btnTriggerClicked)
self.customSig.connect(self.customSlot)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.setWindowTitle("这是标题")
window.resize(600,300)
window.show()
sys.exit(app.exec())
运行结果: