语之屋

PySide6开发日记(一)

2024-11-11
pythonPySide6周记
8分钟
1406字

PySide6开发日记(一)

前言

  今年早些时候,为国产读书书摘记录软件做了一个api导入程序,第一版发布后有两个用户,但后面就没关注这个程序了,半个月之前其中一位用户向我询问能否为程序增加一些新的功能,就此我开始程序v0.2版本的开发。

  程序名字是《merpyzf_pyside6》,顾名思义,技术栈是PySide6,于是继续一边学习一边写新功能,目前来看新版本开发会持续几周,索性就当作周记,每周记录自己的学习心得。

笔记一:程序的顶部状态栏

1. 隐藏系统状态栏

  虽然暂时没有打算做Mac OS和Linux版本,但是Windows的系统UI已经让我大为不爽了,于是开始研究无边框模式,搜到了许多教程,但实测下来能用的确实都有各种各样的问题。

  最后连带AI和各种资料总算是写出了我需要的代码。

1
from PySide6.QtCore import *
2
from PySide6.QtGui import *
3
from PySide6.QtWidgets import *
4
5
if __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组件。

  于是第一版程序很快就写出来了:

1
from PySide6.QtGui import *
2
from PySide6.QtWidgets import *
3
4
5
def window_max(): ...
6
7
8
if __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()

  运行效果:

default

3 窗口拖动

  隐藏窗口一时爽,隐藏以后动不了,当我发现窗口开始变得不能移动后人都傻掉了,只好开始寻找方法。

  处理方法也不难,当我发现PySide6中存在三个函数(mousePressEvent​、mouseMoveEvent​、mouseReleaseEvent​)后,这件事就变得简单起来。

1
from PySide6.QtGui import *
2
from PySide6.QtWidgets import *
3
4
5
class 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 = True
12
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_pos
20
) # 计算新的鼠标全局坐标与初始位置的差值
21
self.move(int(m_Point.x()), int(m_Point.y())) # 根据差值移动窗口到新的位置
22
event.accept() # 接受事件,不再传递
23
24
def mouseReleaseEvent(self, event): # 鼠标按键释放时,取消移动
25
self._move_drag = False
26
event.accept()
27
28
def window_max(self):
29
if self.isMaximized():
30
self.showNormal()
31
32
else:
33
self.showMaximized()
34
35
36
if __name__ == "__main__":
37
app = QApplication([])
38
39
window = QMainWindow()
40
window.setWindowTitle("隐藏系统状态栏")
41
window.resize(400, 300)
42
43
window._move_drag = False
44
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()

  不过今天在写博客时,我发现了一个新的办法,不需要重写这三个方法,看起来更加的简洁实用:

1
from PySide6.QtGui import *
2
from PySide6.QtWidgets import *
3
4
5
class 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
20
if __name__ == "__main__":
21
app = QApplication([])
22
23
window = QMainWindow()
24
window.setWindowTitle("隐藏系统状态栏")
25
window.resize(400, 300)
26
27
window._move_drag = False
28
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_bar
72
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上时才会执行,更加符合使用习惯了吧哈哈哈。


未完事项

  • 实现拖动边框进行窗口的大小设置;

  ‍

本文标题:PySide6开发日记(一)
文章作者:公子语
发布时间:2024-11-11
总访问量
总访客数人次