[TOC]
# 补十六 Python桌面应用开发
本章将介绍基于PyQt/PySide的Python桌面应用开发。
## XVI-1 示例程序
参考[Python GUI教程](https://zmister.com/archives/477.html)[1]
## XVI-2 QtDesigner设计界面
### XVI-2.1 示例界面-QStackedWidget
效果图
![](https://img.kancloud.cn/5e/3a/5e3a6bdf8e1e6f01aea3295a25135bea_1000x688.png)
1、布局对象
![](https://img.kancloud.cn/99/9e/999e7c9b88d8ad9679b139f7cb595826_545x536.png)
2、画出基本布局后,需实现通过点击左侧按钮切换QStackedWidget。思路为将QPushButton的clicked信号绑定至切换QStackedWidget的切换工作区事件。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Python
widget.findChild(QPushButton, "nav_btn_1").clicked.connect(
lambda: widget.findChild(
QStackedWidget,
"workspace"
).setCurrentIndex(0)
)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3、设置点下按钮高亮。具体方法为将checkable、autoExclusive置为true,并设置QPushButton::checked高亮样式。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ css
QPushButton::checked {
background: rgba(245, 245, 245, 0.4);
font-weight: bold;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
![](https://img.kancloud.cn/ce/10/ce1031fec8313d141d7e316683165d1b_539x274.png)
## XVI-3 QSS
QSS基本语法与CSS一致,下文将介绍QSS选择器。
### XVI-3.1 QSS 选择器
Qt 样式表支持CSS2 中定义的所有选择器。下表总结了常用的选择器类型[2]。
| **选择器** | **例子** | **解释** |
|------------|---------------------------|-------------------------------------------------------------------------------------------|
| 通用选择器 | \* | 匹配所有组件。 |
| 类型选择器 | QPushButton | 匹配QPushButton及其子类的实例。 |
| 属性选择器 | QPushButton[flat="false"] | 匹配flat=false的QPushButton实例。此外,还支持特殊属性,请参阅使用动态属性[2]进行自定义。 |
| 类选择器 | .QPushButton | 匹配QPushButton 的实例,但不匹配其子类。 这相当于\*[class\~="QPushButton"]. |
| ID 选择器 | QPushButton\#okButton | 匹配对象名称为 的所有QPushButton实例。okButton |
| 后代选择器 | QDialog QPushButton | 匹配QDialog 的所有后代(子、孙等)的QPushButton实例。 |
| 子选择器 | QDialog \> QPushButton | 匹配QDialog 的直接子级[QPushButton 的](https://doc.qt.io/qt-6/qpushbutton.html)所有实例。 |
### XVI-3.2 引用外联式QSS
调用Application的setStyleSheet(qssStyle)方法即可引入外联QSS,qssStyle为读取qss文件内字符串。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ python
app = QApplication([])
win = QMainWindow()
# SECTION 引入QSS [liuxl-20210915-2156]
styleFile = 'assets/style.qss'
qssStyle = ResourceUtils.getQss(styleFile)
app.setStyleSheet(qssStyle)
# !SECTION [liuxl-20210915-2156]
mainWindow = Ui_MainWindow()
mainWindow.setupUi(win)
win.show()
app.exec()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## XVI-4信号与槽
## XVI-A 常见问题
### 引用qrc文件
在QtDesigner资源管理器中新增、编辑qrc文件后,需编译为resources_rc.py才能被python代码调用,编译命令如下:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ shell
pyside6-rcc resources.qrc -o resources_rc
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### 无边框窗口拖拽
隐藏系统边框后,窗口将不能长按鼠标拖拽移动窗口。实现拖拽方法如下
1、编写QtFramlessWindow类(继承QWidget),重写mouseMoveEvent方法。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ python
class QtFramelessWindow(QWidget):
def __init__(self, main_window) -> None:
super(QtFramelessWindow, self).__init__(None, Qt.FramelessWindowHint)
self._main_window = main_window
self.setWindowFlags(QtCore.Qt.Widget | QtCore.Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_NoSystemBackground, True)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
self.clicked = False
def mousePressEvent(self, ev):
self.old_pos = ev.screenPos()
def mouseMoveEvent(self, ev):
if self.clicked:
dx = self.old_pos.x() - ev.screenPos().x()
dy = self.old_pos.y() - ev.screenPos().y()
self._main_window.move(self._main_window.pos().x() - dx, self._main_window.pos().y() - dy)
self.old_pos = ev.screenPos()
self.clicked = True
return QWidget.mouseMoveEvent(self, ev)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2、在QtDesigner中,将MainWindow的子元素提升为QtFramlessWindow。
![](https://img.kancloud.cn/b8/96/b896b02bb4baa204e8fb11fec57ebbc2_764x795.png)
# 参考文献
[1] 佚名. Python GUI教程(十六):在PyQt5中美化和装扮图形界面 -
州的先生[EB/OL]([日期不详])[2021–09–16]. https://zmister.com/archives/477.html.
[2] 佚名. The Style Sheet Syntax \| Qt Widgets
6.1.3[EB/OL]([日期不详])[2021–09–16].
https://doc.qt.io/qt-6/stylesheet-syntax.html.