PySide6开发日记(一)
前言
今年早些时候,为国产读书书摘记录软件做了一个api导入程序,第一版发布后有两个用户,但后面就没关注这个程序了,半个月之前其中一位用户向我询问能否为程序增加一些新的功能,就此我开始程序v0.2版本的开发。
程序名字是《merpyzf_pyside6》,顾名思义,技术栈是PySide6,于是继续一边学习一边写新功能,目前来看新版本开发会持续几周,索性就当作周记,每周记录自己的学习心得。
笔记一:程序的顶部状态栏
1. 隐藏系统状态栏
虽然暂时没有打算做Mac OS和Linux版本,但是Windows的系统UI已经让我大为不爽了,于是开始研究无边框模式,搜到了许多教程,但实测下来能用的确实都有各种各样的问题。
最后连带AI和各种资料总算是写出了我需要的代码。
1from PySide6.QtCore import *2from PySide6.QtGui import *3from PySide6.QtWidgets import *4
5if __name__ == '__main__':6 app = QApplication([])7
8 window = QMainWindow()9 window.setWindowTitle('隐藏系统状态栏')10 window.resize(400, 300)11
12 layout = QVBoxLayout(window)13 label = QLabel('这是一个无状态栏示例')14 layout.addWidget(label)15
5 collapsed lines
16 # 隐藏状态栏17 window.setWindowFlag(Qt.WindowType.FramelessWindowHint)18
19 window.show()20 app.exec()
核心部分就是setWindowFlag
。起初我在网络上查找相关代码时看到了许多教程,但是当我尝试导入Qt时,显示在QtCore、QtGui类下都存在Qt库,便一直没能成功,最后索性使用*
进行导入。
2. 设置最大化,最小化以及关闭程序按钮,并放置在合适的位置
三个按钮很好搞定,QPushbutton+icon属性就搞定了。
我想到可以用菜单栏用于放置它们,PySide6中当然也有相关的功能,QToolBar组件。
于是第一版程序很快就写出来了:
1from PySide6.QtGui import *2from PySide6.QtWidgets import *3
4
5def window_max(): ...6
7
8if __name__ == "__main__":9 app = QApplication([])10
11 window = QMainWindow()12 window.setWindowTitle("隐藏系统状态栏")13 window.resize(400, 300)14
15 widget_center = QWidget()42 collapsed lines
16 layout = QVBoxLayout(widget_center)17 label = QLabel("这是一个无状态栏示例")18 layout.addWidget(label)19
20 # 隐藏状态栏21 window.setWindowFlag(Qt.WindowType.FramelessWindowHint)22
23 toolbar = QToolBar()24 # 设置工具栏不可移动25 toolbar.setMovable(False)26
27 # 填充工具栏左侧,让三个按钮被放置到最右侧28 widget_fill = QWidget()29 toolbar.addWidget(widget_fill)30 layout_toolbar = QHBoxLayout(widget_fill)31 layout_toolbar.addStretch()32
33 # 设置三个按钮,并将其设置为图片形式34 btn_min = QPushButton(icon=QIcon("assets/min.svg"))35 btn_max = QPushButton(icon=QIcon("assets/icon-max.svg"))36 btn_close = QPushButton(icon=QIcon("assets/close.svg"))37
38 # 去除按钮边框39 btn_min.setFlat(True)40 btn_max.setFlat(True)41 btn_close.setFlat(True)42
43 # 将按钮放置在toolbar上44 toolbar.addWidget(btn_min)45 toolbar.addWidget(btn_max)46 toolbar.addWidget(btn_close)47
48 # 为按钮增加功能,其中最大化按钮需要额外函数进行修饰49 btn_min.clicked.connect(window.showMinimized)50 btn_max.clicked.connect(lambda: window_max())51 btn_close.clicked.connect(window.close)52
53 # 将toolbar放置到window上54 window.addToolBar(toolbar)55 window.setCentralWidget(widget_center)56 window.show()57 app.exec()
运行效果:
3 窗口拖动
隐藏窗口一时爽,隐藏以后动不了,当我发现窗口开始变得不能移动后人都傻掉了,只好开始寻找方法。
处理方法也不难,当我发现PySide6中存在三个函数(mousePressEvent
、mouseMoveEvent
、mouseReleaseEvent
)后,这件事就变得简单起来。
1from PySide6.QtGui import *2from PySide6.QtWidgets import *3
4
5class QMainWindow(QMainWindow):6 def __init__(self):7 super().__init__()8
9 def mousePressEvent(self, event): # 当鼠标按钮被按下时调用此函数10 if event.button() == Qt.LeftButton:11 self._move_drag = True12 self.cursor_win_pos = event.globalPosition() - self.pos()13 event.accept()14
15 def mouseMoveEvent(self, event): # 当鼠标移动时调用此函数73 collapsed lines
16 # 如果鼠标左键被按下并且可以拖动窗口17 if Qt.LeftButton and self._move_drag:18 m_Point = (19 event.globalPosition() - self.cursor_win_pos20 ) # 计算新的鼠标全局坐标与初始位置的差值21 self.move(int(m_Point.x()), int(m_Point.y())) # 根据差值移动窗口到新的位置22 event.accept() # 接受事件,不再传递23
24 def mouseReleaseEvent(self, event): # 鼠标按键释放时,取消移动25 self._move_drag = False26 event.accept()27
28 def window_max(self):29 if self.isMaximized():30 self.showNormal()31
32 else:33 self.showMaximized()34
35
36if __name__ == "__main__":37 app = QApplication([])38
39 window = QMainWindow()40 window.setWindowTitle("隐藏系统状态栏")41 window.resize(400, 300)42
43 window._move_drag = False44
45 widget_center = QWidget()46 layout = QVBoxLayout(widget_center)47 label = QLabel("这是一个无状态栏示例")48 layout.addWidget(label)49
50 # 隐藏状态栏51 window.setWindowFlag(Qt.WindowType.FramelessWindowHint)52
53 toolbar = QToolBar()54 # 设置工具栏不可移动55 toolbar.setMovable(False)56
57 # 填充工具栏左侧,让三个按钮被放置到最右侧58 widget_fill = QWidget()59 toolbar.addWidget(widget_fill)60 layout_toolbar = QHBoxLayout(widget_fill)61 layout_toolbar.addStretch()62
63 # 设置三个按钮,并将其设置为图片形式64 btn_min = QPushButton(icon=QIcon("assets/min.svg"))65 btn_max = QPushButton(icon=QIcon("assets/icon-max.svg"))66 btn_close = QPushButton(icon=QIcon("assets/close.svg"))67
68 # 去除边框69 btn_min.setFlat(True)70 btn_max.setFlat(True)71 btn_close.setFlat(True)72
73 # 将按钮放置在toolbar上74 toolbar.addWidget(btn_min)75 toolbar.addWidget(btn_max)76 toolbar.addWidget(btn_close)77
78 # 为按钮增加功能,其中最大化按钮需要额外函数进行修饰79 btn_min.clicked.connect(window.showMinimized)80 btn_max.clicked.connect(lambda: window.window_max())81 btn_close.clicked.connect(window.close)82
83 # 将toolbar放置到window上84 window.addToolBar(toolbar)85 window.setCentralWidget(widget_center)86
87 window.show()88 app.exec()
不过今天在写博客时,我发现了一个新的办法,不需要重写这三个方法,看起来更加的简洁实用:
1from PySide6.QtGui import *2from PySide6.QtWidgets import *3
4
5class QMainWindow(QMainWindow):6 def __init__(self):7 super().__init__()8
9 def window_max(self):10 if self.isMaximized():11 self.showNormal()12
13 else:14 self.showMaximized()15
59 collapsed lines
16 def move_title_bar(self, event):17 self.windowHandle().startSystemMove()18
19
20if __name__ == "__main__":21 app = QApplication([])22
23 window = QMainWindow()24 window.setWindowTitle("隐藏系统状态栏")25 window.resize(400, 300)26
27 window._move_drag = False28
29 widget_center = QWidget()30 layout = QVBoxLayout(widget_center)31 label = QLabel("这是一个无状态栏示例")32 layout.addWidget(label)33
34 # 隐藏状态栏35 window.setWindowFlag(Qt.WindowType.FramelessWindowHint)36
37 toolbar = QToolBar()38 # 设置工具栏不可移动39 toolbar.setMovable(False)40
41 # 填充工具栏左侧,让三个按钮被放置到最右侧42 widget_fill = QWidget()43 toolbar.addWidget(widget_fill)44 layout_toolbar = QHBoxLayout(widget_fill)45 layout_toolbar.addStretch()46
47 # 设置三个按钮,并将其设置为图片形式48 btn_min = QPushButton(icon=QIcon("assets/min.svg"))49 btn_max = QPushButton(icon=QIcon("assets/icon-max.svg"))50 btn_close = QPushButton(icon=QIcon("assets/close.svg"))51
52 # 去除边框53 btn_min.setFlat(True)54 btn_max.setFlat(True)55 btn_close.setFlat(True)56
57 # 将按钮放置在toolbar上58 toolbar.addWidget(btn_min)59 toolbar.addWidget(btn_max)60 toolbar.addWidget(btn_close)61
62 # 为按钮增加功能,其中最大化按钮需要额外函数进行修饰63 btn_min.clicked.connect(window.showMinimized)64 btn_max.clicked.connect(lambda: window.window_max())65 btn_close.clicked.connect(window.close)66
67 # 将toolbar放置到window上68 window.addToolBar(toolbar)69 window.setCentralWidget(widget_center)70
71 toolbar.mouseMoveEvent = window.move_title_bar72
73 window.show()74 app.exec()
其实核心部分只有以下两点:
1 def move_title_bar(self, event):2 self.windowHandle().startSystemMove()
1 toolbar.mouseMoveEvent = window.move_title_bar
不仅实现了移动,而且只有光标在toolbar上时才会执行,更加符合使用习惯了吧哈哈哈。
未完事项
- 实现拖动边框进行窗口的大小设置;