首页 >> 大全

PyQt窗口FramelessWindowHint模式下自定义窗口缩放与移动功能

2023-06-22 大全 51 作者:考证青年

背景

众所周知,PyQt的窗口支持隐藏系统默认的窗口,实现自定义窗口的样式。

但是,启用这种模式的窗口随之而来的问题是:无法使用系统默认的窗口缩放,窗口移动等功能。因此,今天博主带来自己编写的一个自定义窗口类,需要使用的小伙伴可以直接下载此代码,将您自己的窗口类继承该类即可拥有以下功能。

self.setWindowFlags(Qt.FramelessWindowHint)

功能 部分功能演示

原理 源代码 1、定制窗口基类

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtCore import Qt'''
定制窗口基类
@Author: 浅若清风cyf
@Date: 2023/06/16
@Description: 支持窗口缩放,标题栏双击最大最小化,解决了依赖mouseMoveEvent识别鼠标位置导致鼠标样式更新不及时的问题
'''class MainWinCustom(QMainWindow):def __init__(self, titleHeight: int = 20):super(MainWinCustom, self).__init__()# 鼠标拖拽缩放窗口的识别区域宽度self._padding = 20# 设置标题栏的高度,作为双击标题栏的识别区域范围self.titleHeight = titleHeight# 隐藏系统默认框架self.setWindowFlags(Qt.FramelessWindowHint)# 一些鼠标状态self.is_mousePressed = Falseself.is_resizing = Falseself.resize_direction = 'right'# 一些功能启用状态self.support_resize = Trueself.support_double_max = Trueself.timer_cursorUpdater = QTimer(self)def set_mouse_tracking(self):self.ui.frame.setMouseTracking(True)self.ui.centralwidget.setMouseTracking(True)self.setMouseTracking(True)  # / 设置widget鼠标跟踪def disable_window_resize(self):self.support_resize = Falseself.stop_cursorUpdater()def disable_double_max(self):self.support_double_max = Falsedef set_titleHeight(self, height: int):self.titleHeight = heightdef set_frame_style(self, frame: QFrame):frame.setFrameStyle(QFrame.Panel)def set_comboBoxView(self):comboBoxes = self.findChildren(QComboBox)for comboBox in comboBoxes:comboBox.setView(QListView())def set_max_button(self, btn: QToolButton or QPushButton):btn.clicked.connect(self.change_window_size)def set_min_button(self, btn: QToolButton or QPushButton):btn.clicked.connect(self.showMinimized)def set_close_button(self, btn: QToolButton or QPushButton):btn.clicked.connect(self.close)'''以下重写窗口拖拽事件'''def resizeEvent(self, QResizeEvent):# 获取有效识别区域self.right_l = self.width() - self._paddingself.right_r = self.width() + 1self.bottom_u = self.height() - self._paddingself.bottom_d = self.height() + 1# # 识别区域# print('x识别区间:', self.right_l, ',', self.right_r)# print('y识别区间:', self.bottom_u, ',', self.bottom_d)def get_mouse_pos_of_window(self) -> QPoint:global_pos = QCursor.pos()window_pos = self.mapFromGlobal(global_pos)return window_posdef get_mouse_global_pos(self) -> QPoint:return QCursor.pos()def check_pos_status(self):'''获取鼠标相对于窗口的坐标,根据鼠标所处的位置返回鼠标的状态'''pos: QPoint = self.get_mouse_pos_of_window()if pos.x() >= self.right_l and pos.x() < self.right_r:if pos.y() >= 0:if pos.y() <= self.bottom_u:return pos, "right"  # 右边界elif pos.y() < self.bottom_d:return pos, "corner"  # 右下角if pos.y() >= self.bottom_u and pos.y() < self.bottom_d:if pos.x() >= 0:if pos.x() <= self.right_l:return pos, 'bottom'  # 下边界if pos.x() >= 0 and pos.x() <= self.right_l and pos.y() >= 0 and pos.y() <= self.titleHeight:return pos, 'title'return pos, Falsedef start_cursorUpdater(self):'''启动计时器更新鼠标样式'''if self.timer_cursorUpdater:self.timer_cursorUpdater.timeout.connect(self.update_cursor)self.timer_cursorUpdater.start(100)  # 每隔1秒触发一次鼠标移动事件def stop_cursorUpdater(self):'''停止计时器更新鼠标样式'''if self.timer_cursorUpdater:self.timer_cursorUpdater.stop()def update_cursor(self):'''根据鼠标坐标获取状态,设定鼠标样式'''pos, status = self.check_pos_status()if status is False:self.setCursor(Qt.ArrowCursor)elif status == 'right':self.setCursor(Qt.SizeHorCursor)elif status == 'bottom':self.setCursor(Qt.SizeVerCursor)elif status == 'corner':self.setCursor(Qt.SizeFDiagCursor)else:self.setCursor(Qt.ArrowCursor)def change_window_size(self):if not self.isMaximized():self.showMaximized()self.stop_cursorUpdater()elif self.isMaximized():self.showNormal()self.start_cursorUpdater()return self.isMaximized()def mousePressEvent(self, event: QMouseEvent):self.is_mousePressed = Trueself.mouse_pos = self.get_mouse_global_pos()def mouseReleaseEvent(self, event: QMouseEvent):self.is_mousePressed = Falseself.is_resizing = Falsedef mouseDoubleClickEvent(self, *args, **kwargs):'''检测标题栏的双击状态,切换最大化与正常窗口'''if self.check_pos_status()[1] == 'title' and self.support_double_max:self.change_window_size()def mouseMoveEvent(self, event: QMouseEvent):if self.is_resizing:pos = self.get_mouse_pos_of_window()if self.resize_direction == 'right' and self.support_resize:self.resize(pos.x(), self.height())elif self.resize_direction == 'down' and self.support_resize:self.resize(self.width(), pos.y())elif self.resize_direction == 'right-down' and self.support_resize:self.resize(pos.x(), pos.y())elif self.resize_direction == 'move':current_pos = self.get_mouse_global_pos()self.move(self.pos() + current_pos - self.mouse_pos)self.mouse_pos = current_poselse:if self.is_mousePressed:pos, status = self.check_pos_status()if status is False:self.is_resizing = Falseif status == 'right':# self.resize(pos.x(), self.height())self.is_resizing = Trueself.resize_direction = 'right'elif status == 'bottom':self.is_resizing = Trueself.resize_direction = 'down'elif status == 'corner':self.is_resizing = Trueself.resize_direction = 'right-down'elif status == 'title':self.is_resizing = Trueself.resize_direction = 'move'def hideEvent(self, *args, **kwargs):self.stop_cursorUpdater()def showEvent(self, *args, **kwargs):if self.support_resize:self.start_cursorUpdater()

2、使用示例

class MyWin(MainWinCustom):def __init__(self):super(MyWin2, self).__init__()self.resize(200, 300)# 创建一个 QWidget 作为中心区域的容器central_widget = QWidget(self)# 在中心容器中添加其他控件label_title = QLabel("这是标题栏", central_widget)label_title.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)label_title.setFixedHeight(40)label_title.setStyleSheet("""QLabel{background: yellow;}""")layout = QVBoxLayout(central_widget)layout.addWidget(label_title)label = QLabel('Power by 浅若清风cyf\n\t2023/06/16\n')label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)layout.addWidget(label)layout.setContentsMargins(0, 0, 0, 0)# 将中心容器设置为 QMainWindow 的中心部件self.setCentralWidget(central_widget)# 设置label_title的高度为有效识别区域self.set_titleHeight(label_title.height())if __name__ == '__main__':QtCore.QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)QtGui.QGuiApplication.setAttribute(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough) app = QApplication(sys.argv)win = MyWin()win.show()sys.exit(app.exec_())

tags: pyqt

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了