前提:UI必須采用自适应布局。
- # 自定义组件
- """
- QCustomTitleBar:自定义标题
- QWindowMoveResize:自定义缩放和拖动
- """
- import PySide6.QtGui
- from PySide6.QtGui import QPainter, QBrush
- from PySide6 import QtGui, QtWidgets, QtCore
- from PySide6.QtCore import Qt, QSize, QRect
- from PySide6.QtWidgets import QPushButton, QLabel, QWidget, QProgressBar, QHBoxLayout, QDialog
-
-
- # 自定义标题栏
- class QCustomTitleBar:
- def __init__(self, window: QtWidgets):
- self.window = window
- # 默认标题栏高度 必须设
- self.DEFAULT_TITILE_BAR_HEIGHT = 40
- # 存储父类的双击事件
- self.mouseDoubleClickEvent_parent = self.window.mouseDoubleClickEvent
- # 将本类的双击事件赋值给将父类的双击事件
- self.window.mouseDoubleClickEvent = self.mouseDoubleClickEvent
-
- # 存储父类的窗口大小改变事件
- self.resizeEvent_parent = self.window.resizeEvent
- # 将本类的窗口大小改变事件赋值给将父类的窗口大小改变事件
- self.window.resizeEvent = self.resizeEvent
-
- # 设置ui文件里main_layout上边距,以免遮挡标题栏
- self.window.setContentsMargins(0, self.DEFAULT_TITILE_BAR_HEIGHT, 0, 0)
-
- # 1.设置无边框 和 透明背景 无边框必须设置全,不然会导致点击任务栏不能最小化窗口
- self.window.setWindowFlags(
- Qt.Window
- | Qt.FramelessWindowHint
- | Qt.WindowSystemMenuHint
- | Qt.WindowMinimizeButtonHint
- | Qt.WindowMaximizeButtonHint
- )
- # self.window.setAttribute(Qt.WA_TranslucentBackground)
- # 2.添加自定义的标题栏到最顶部
- self.title = QLabel("", self.window)
- # 3.设置标题栏样式
- self.setStyle()
- # 4.添加按钮
- # 添加关闭按钮
- self.close_btn = QPushButton("", self.window)
- self.close_btn.setGeometry(self.window.width() - 33, 10, 20, 20)
- # 添加最大化按钮
- self.max_btn = QPushButton("", self.window)
- self.max_btn.setGeometry(self.window.width() - 66, 10, 20, 20)
- # 添加最小化按钮
- self.min_btn = QPushButton("", self.window)
- self.min_btn.setGeometry(self.window.width() - 99, 10, 20, 20)
- # 设置三个按钮的鼠标样式
- self.close_btn.setCursor(Qt.PointingHandCursor)
- self.max_btn.setCursor(Qt.PointingHandCursor)
- self.min_btn.setCursor(Qt.PointingHandCursor)
- # 设置三个按钮的样式
- self.close_btn.setStyleSheet(
- "QPushButton{border-image:url('./images/close.png');background:#ff625f;border-radius:10px;}"
- "QPushButton:hover{background:#eb4845;}"
- )
- self.max_btn.setStyleSheet(
- "QPushButton{border-image:url('./images/max.png');background:#ffbe2f;border-radius:10px;}"
- "QPushButton:hover{background:#ecae27;}"
- )
- self.min_btn.setStyleSheet(
- "QPushButton{border-image:url('./images/min.png');background:#29c941;border-radius:10px;}"
- "QPushButton:hover{background:#1ac033;}"
- )
-
- # 5.添加工具栏按钮事件
- # 关闭按钮点击绑定窗口关闭事件
- self.close_btn.pressed.connect(self.window.close)
- # 最大化按钮绑定窗口最大化事件
- self.max_btn.pressed.connect(self.setMaxEvent)
- # 最小化按钮绑定窗口最小化事件
- self.min_btn.pressed.connect(self.window.showMinimized)
- # 6.记录全屏窗口的大小-ps非常有用
- self.window_max_size = None
- # 7.设置标题栏鼠标跟踪 鼠标移入触发,不设置,移入标题栏不触发
- self.title.setMouseTracking(True)
-
- def setMaxEvent(self, flag=False):
- """
- @description 最大化按钮绑定窗口最大化事件和事件 拿出来是因为拖动标题栏时需要恢复界面大小
- @param flag 是否是拖动标题栏 bool
- @return
- """
- if flag:
- if self.window.isMaximized():
- self.window.showNormal()
- self.max_btn.setStyleSheet(
- "QPushButton{border-image:url('./images/max.png');background:#ffbe2f;border-radius:10px;}"
- "QPushButton:hover{background:#ecae27;}"
- )
- return self.window_max_size
- return None
- else:
- if self.window.isMaximized():
- self.window.showNormal()
- self.max_btn.setStyleSheet(
- "QPushButton{border-image:url('./images/max.png');background:#ffbe2f;border-radius:10px;}"
- "QPushButton:hover{background:#ecae27;}"
- )
- else:
- self.window.showMaximized()
- self.max_btn.setStyleSheet(
- "QPushButton{border-image:url('./images/restore.png');background:#ffbe2f;border-radius:10px;}"
- "QPushButton:hover{background:#ecae27;}"
- )
- # 记录最大化窗口的大小 用于返回最大化时拖动窗口恢复前的大小 这个程序循环帧会取不到恢复前的宽度
- self.window_max_size = QSize(self.window.width(), self.window.height())
-
- def setStyle(self, style: str = ""):
- """
- @description 设置自定义标题栏样式
- @param
- @return
- """
- # 想要边框 加上border:1px solid #cccccc;
- DEFAULT_STYLE = """
- background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #fafafa,stop:1 #d1d1d1);
- color:#333333;padding:10px;border:1px solid #c6c6c6;
- border-top-left-radius:4px;
- border-top-right-radius:4px;
- """
- self.title.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
- # 设置样式
- self.title.setStyleSheet(DEFAULT_STYLE if not style else DEFAULT_STYLE + style)
- # 设置大小
- self.title.setGeometry(0, 0, self.window.width(), self.DEFAULT_TITILE_BAR_HEIGHT)
-
- def mouseDoubleClickEvent(self, a0: QtGui.QMouseEvent) -> None:
- """
- @description 鼠标双击事件
- @param
- @return
- """
- # 如果双击的是鼠标左键 且在标题栏范围内 则放大缩小窗口
- if a0.button() == Qt.MouseButton.LeftButton and a0.position().y() < self.title.height():
- self.setMaxEvent()
- return self.mouseDoubleClickEvent_parent(a0)
-
- def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
- """
- @description 窗口缩放事件
- @param
- @return
- """
- # 最大化最小化的时候,需要去改变按钮组位置
- self.close_btn.move(self.window.width() - 33, 10)
- self.max_btn.move(self.window.width() - 66, 10)
- self.min_btn.move(self.window.width() - 99, 10)
- self.title.resize(self.window.width(), self.DEFAULT_TITILE_BAR_HEIGHT)
- return self.resizeEvent_parent(a0)
-
-
- # 实现拖动和缩放Widget
- class QWindowMoveResizeWidget(QWidget):
-
- def __init__(self, parent=None):
- super(QWindowMoveResizeWidget, self).__init__(parent)
- # 1.设置无边框 和 透明背景 无边框必须设置全,不然会导致点击任务栏不能最小化窗口
- self.setWindowFlags(
- Qt.Window
- | Qt.FramelessWindowHint
- | Qt.WindowSystemMenuHint
- | Qt.WindowMinimizeButtonHint
- | Qt.WindowMaximizeButtonHint
- )
- # 设置窗体透明
- self.setAttribute(Qt.WA_TranslucentBackground)
- # 默认标题栏高度 必须设
- self.DEFAULT_TITILE_BAR_HEIGHT = 40
- # 鼠标缩放窗口最小宽度,必须设
- self.MIN_WINDOW_WIDTH = 10
- self.MIN_WINDOW_HEIGHT = 10
- # 鼠标拖动窗口的标识
- self.m_flag = False
- # 初始化鼠标拖动标题栏标志
- self.drag_flag = False
- # 记录按下时窗口坐标, 这个用于窗口移动
- self.win_x = 0
- self.win_y = 0
- # 记录按下时鼠标坐标,这个用于计算鼠标移动的距离
- self.mouse_x = 0
- self.mouse_y = 0
- # 记录鼠标移入的拖动区域,共8种区域 左上 左 左下 上 下 右上 右 右下
- self.left_up = None
- self.left = None
- self.left_down = None
- self.up = None
- self.down = None
- self.right_up = None
- self.right = None
- self.right_down = None
- # 设置为True则mouseMoveEvent事件不需要按下也能触发,不然要按着鼠标左键或右键才能触发
- self.setMouseTracking(True)
- # 设置子类的mousetrack
- # self.centralwidget.setMouseTracking(True)
- # 记录按下时窗口的大小,用于计算鼠标相对于窗口移动的距离,用于缩放
- self.win_w = 0
- self.win_h = 0
- # 初始化鼠标缩放标志
- self.move_left_up_flag = False
- self.move_left_flag = False
- self.move_left_down_flag = False
- self.move_up_flag = False
- self.move_down_flag = False
- self.move_right_up_flag = False
- self.move_right_flag = False
- self.move_right_down_flag = False
-
- # 设置边框圆角
- def paintEvent(self, event: PySide6.QtGui.QPaintEvent) -> None:
- painter = QPainter(self)
- painter.setRenderHint(QPainter.RenderHint.Antialiasing) # 设置抗锯齿,不然边框会有明显锯齿
- painter.setBrush(Qt.white) # 设置窗体颜色
- painter.drawRoundedRect(self.rect(), 10, 10)
- super().paintEvent(event)
-
- def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
- """
- @description 窗口缩放事件
- @param
- @return
- """
- # 最大化最小化的时候,需要去改变按钮组位置
- # self.titleBar.close_btn.move(self.width() - 33, 10)
- # self.titleBar.max_btn.move(self.width() - 66, 10)
- # self.titleBar.min_btn.move(self.width() - 99, 10)
- # self.titleBar.title.resize(self.width(), DEFAULT_TITILE_BAR_HEIGHT)
-
- # 记录鼠标移入的拖动区域,共8种区域
- self.left_up = QRect(0, 0, 10, 10)
- self.left = QRect(0, 10, 10, self.height() - 20)
- self.left_down = QRect(0, self.height() - 10, 10, 10)
- self.up = QRect(10, 0, self.width() - 20, 10)
- self.down = QRect(10, self.height() - 10, self.width() - 20, 10)
- self.right_up = QRect(self.width() - 10, 0, 10, 10)
- self.right = QRect(self.width() - 10, 10, 10, self.height() - 20)
- self.right_down = QRect(self.width() - 10, self.height() - 10, 10, 10)
-
- return super().resizeEvent(a0)
-
- def mousePressEvent(self, a0: QtGui.QMouseEvent) -> None:
- """
- 拖动窗口
- """
- if a0.button() == QtCore.Qt.LeftButton and self.isMaximized() == False and self.cursor().shape() == QtGui.QCursor(
- QtCore.Qt.ArrowCursor).shape():
- self.m_flag = True
- self.m_Position = a0.globalPosition().toPoint() - self.pos() # 获取鼠标相对窗口的位置
- a0.accept()
- self.setCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor)) # 更改鼠标图标
- else:
- """
- @description 鼠标按下事件
- @param
- @return
- """
- # 记录按下时窗口坐标, 这个用于窗口移动
- self.win_x = self.x()
- self.win_y = self.y()
- # 记录按下时鼠标坐标,这个用于计算鼠标移动的距离
- self.mouse_x = a0.globalPosition().x()
- self.mouse_y = a0.globalPosition().y()
- # 记录按下时窗口的大小,用于计算鼠标相对于窗口移动的距离,用于缩放
- self.win_w = self.width()
- self.win_h = self.height()
-
- if not self.isMaximized():
- # 如果按下的是鼠标左键
- if a0.button() == Qt.MouseButton.LeftButton and self.left_up.contains(a0.position().x(),
- a0.position().y()):
- self.move_left_up_flag = True
- if a0.button() == Qt.MouseButton.LeftButton and self.left.contains(a0.position().x(),
- a0.position().y()):
- self.move_left_flag = True
- if a0.button() == Qt.MouseButton.LeftButton and self.left_down.contains(
- a0.position().x(), a0.position().y()
- ):
- self.move_left_down_flag = True
- if a0.button() == Qt.MouseButton.LeftButton and self.up.contains(a0.position().x(), a0.position().y()):
- self.move_up_flag = True
- if a0.button() == Qt.MouseButton.LeftButton and self.down.contains(a0.position().x(),
- a0.position().y()):
- self.move_down_flag = True
- if a0.button() == Qt.MouseButton.LeftButton and self.right_up.contains(
- a0.position().x(), a0.position().y()
- ):
- self.move_right_up_flag = True
- if a0.button() == Qt.MouseButton.LeftButton and self.right.contains(a0.position().x(),
- a0.position().y()):
- self.move_right_flag = True
- if a0.button() == Qt.MouseButton.LeftButton and self.right_down.contains(
- a0.position().x(), a0.position().y()
- ):
- self.move_right_down_flag = True
- return super().mousePressEvent(a0)
-
- def mouseMoveEvent(self, a0: QtGui.QMouseEvent) -> None:
- """
- 拖动窗口
- """
- if QtCore.Qt.LeftButton and self.m_flag and self.cursor().shape() == QtGui.QCursor(
- QtCore.Qt.OpenHandCursor).shape():
- self.move(a0.globalPosition().toPoint() - self.m_Position) # 更改窗口位置
- a0.accept()
- else:
- """
- @description 鼠标按下移动事件
- @param
- @return
- """
- # 获取移动后鼠标的位置
- mouse_move_x = a0.globalPosition().x()
- mouse_move_y = a0.globalPosition().y()
- # 计算移动的距离
- offset_x = mouse_move_x - self.mouse_x
- offset_y = mouse_move_y - self.mouse_y
- # 移动鼠标时设置鼠标样式
- if not self.isMaximized():
- # 不是拖动的时才可能是缩放状态
- if not self.drag_flag:
- # 左上
- if self.left_up.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeFDiagCursor)
- # 左
- elif self.left.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeHorCursor)
- # 左下
- elif self.left_down.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeBDiagCursor)
- # 上
- elif self.up.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeVerCursor)
- # 下
- elif self.down.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeVerCursor)
- # 右上
- elif self.right_up.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeBDiagCursor)
- # 右
- elif self.right.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeHorCursor)
- # 右下
- elif self.right_down.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeFDiagCursor)
- else:
- self.setCursor(Qt.ArrowCursor)
- else:
- self.setCursor(Qt.ArrowCursor)
- else:
- self.setCursor(Qt.ArrowCursor)
- # 如果按下且在左上角范围内则缩放(其他代码参考左上)
- if self.move_left_up_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeFDiagCursor)
- resize_w = self.win_w - offset_x
- resize_h = self.win_h - offset_y
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_w
- resize_h = self.MIN_WINDOW_HEIGHT if resize_h < self.MIN_WINDOW_HEIGHT else resize_h
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 设置窗口移动,需要鼠标跟随
- # x y 都要鼠标跟随
- if resize_w != self.MIN_WINDOW_WIDTH and resize_h != self.MIN_WINDOW_HEIGHT:
- self.move(self.win_x + offset_x, self.win_y + offset_y)
- # 缩放宽度等于最小宽度,高度鼠标跟随
- if resize_w == self.MIN_WINDOW_WIDTH and resize_h != self.MIN_WINDOW_HEIGHT:
- self.move(self.x(), self.win_y + offset_y)
- # 缩放高度等于最小高度,宽度鼠标跟随
- if resize_w != self.MIN_WINDOW_WIDTH and resize_h == self.MIN_WINDOW_HEIGHT:
- self.move(self.win_x + offset_x, self.y())
- # 如果按下且在左边范围内则缩放
- elif self.move_left_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeHorCursor)
- resize_w = self.win_w - offset_x
- resize_h = self.win_h
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_w
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 设置窗口移动,需要鼠标跟随
- # 只要宽度鼠标跟随
- if resize_w != self.MIN_WINDOW_WIDTH:
- self.move(self.win_x + offset_x, self.win_y)
- # 如果按下且在左下角范围内则缩放
- elif self.move_left_down_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeBDiagCursor)
- resize_w = self.win_w - offset_x
- resize_h = self.win_h + offset_y
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_w
- resize_h = self.MIN_WINDOW_HEIGHT if resize_h < self.MIN_WINDOW_HEIGHT else resize_h
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 设置窗口移动,需要鼠标跟随
- # x y 都要鼠标跟随
- if resize_w != self.MIN_WINDOW_WIDTH and resize_h != self.MIN_WINDOW_HEIGHT:
- self.move(self.win_x + offset_x, self.y())
- # 缩放高度等于最小高度,宽度鼠标跟随
- if resize_w != self.MIN_WINDOW_WIDTH and resize_h == self.MIN_WINDOW_HEIGHT:
- self.move(self.win_x + offset_x, self.y())
- # 如果按下且在上边范围内则缩放
- elif self.move_up_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeVerCursor)
- resize_w = self.win_w
- resize_h = self.win_h - offset_y
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_h = self.MIN_WINDOW_HEIGHT if resize_h < self.MIN_WINDOW_HEIGHT else resize_h
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 设置窗口移动,需要鼠标跟随
- # 只要高度鼠标跟随
- if resize_h != self.MIN_WINDOW_HEIGHT:
- self.move(self.win_x, self.win_y + offset_y)
- # 如果按下且在下边范围内则缩放
- elif self.move_down_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeVerCursor)
- resize_w = self.win_w
- resize_h = self.win_h + offset_y
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_h = self.MIN_WINDOW_HEIGHT if resize_h < self.MIN_WINDOW_HEIGHT else resize_h
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 如果按下且在右上角范围内则缩放
- elif self.move_right_up_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeBDiagCursor)
- resize_w = self.win_w + offset_x
- resize_h = self.win_h - offset_y
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_w
- resize_h = self.MIN_WINDOW_HEIGHT if resize_h < self.MIN_WINDOW_HEIGHT else resize_h
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 设置窗口移动,需要鼠标跟随
- # x y 都要鼠标跟随
- if resize_w != self.MIN_WINDOW_WIDTH and resize_h != self.MIN_WINDOW_HEIGHT:
- self.move(self.win_x, self.win_y + offset_y)
- # 缩放宽度等于最小宽度,高度鼠标跟随
- if resize_w == self.MIN_WINDOW_WIDTH and resize_h != self.MIN_WINDOW_HEIGHT:
- self.move(self.x(), self.win_y + offset_y)
- # 如果按下且在右边范围内则缩放
- elif self.move_right_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeHorCursor)
- resize_w = self.win_w + offset_x
- resize_h = self.win_h
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_w
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 如果按下且在右下角范围内则缩放
- elif self.move_right_down_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeFDiagCursor)
- resize_w = self.win_w + offset_x
- resize_h = self.win_h + offset_y
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_w
- resize_h = self.MIN_WINDOW_HEIGHT if resize_h < self.MIN_WINDOW_HEIGHT else resize_h
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 如果按下才能移动
- elif self.drag_flag:
- # 设置窗口移动的距离
- self.move(self.win_x + offset_x, self.win_y + offset_y)
- return super().mouseMoveEvent(a0)
-
- def mouseReleaseEvent(self, a0: QtGui.QMouseEvent) -> None:
- self.m_flag = False
- self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
- """
- @description 鼠标按下松开事件
- @param
- @return
- """
- self.drag_flag = False
- self.move_left_up_flag = False
- self.move_left_flag = False
- self.move_left_down_flag = False
- self.move_up_flag = False
- self.move_down_flag = False
- self.move_right_up_flag = False
- self.move_right_flag = False
- self.move_right_down_flag = False
- self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
- return super().mouseReleaseEvent(a0)
-
-
- # 实现拖动和缩放Dialog
- class QWindowMoveResizeDialog(QDialog):
-
- def __init__(self, parent=None):
- super(QWindowMoveResizeDialog, self).__init__(parent)
- # 1.设置无边框 和 透明背景 无边框必须设置全,不然会导致点击任务栏不能最小化窗口
- self.setWindowFlags(
- Qt.Window
- | Qt.FramelessWindowHint
- | Qt.WindowSystemMenuHint
- | Qt.WindowMinimizeButtonHint
- | Qt.WindowMaximizeButtonHint
- )
- # 窗体透明
- self.setAttribute(Qt.WA_TranslucentBackground)
- # 默认标题栏高度 必须设
- self.DEFAULT_TITILE_BAR_HEIGHT = 40
- # 鼠标缩放窗口最小宽度,必须设
- self.MIN_WINDOW_WIDTH = 10
- self.MIN_WINDOW_HEIGHT = 10
- # 鼠标拖动窗口的标识
- self.m_flag = False
- # 初始化鼠标拖动标题栏标志
- self.drag_flag = False
- # 记录按下时窗口坐标, 这个用于窗口移动
- self.win_x = 0
- self.win_y = 0
- # 记录按下时鼠标坐标,这个用于计算鼠标移动的距离
- self.mouse_x = 0
- self.mouse_y = 0
- # 记录鼠标移入的拖动区域,共8种区域 左上 左 左下 上 下 右上 右 右下
- self.left_up = None
- self.left = None
- self.left_down = None
- self.up = None
- self.down = None
- self.right_up = None
- self.right = None
- self.right_down = None
- # 设置为True则mouseMoveEvent事件不需要按下也能触发,不然要按着鼠标左键或右键才能触发
- self.setMouseTracking(True)
- # 设置子类的mousetrack
- # self.centralwidget.setMouseTracking(True)
- # 记录按下时窗口的大小,用于计算鼠标相对于窗口移动的距离,用于缩放
- self.win_w = 0
- self.win_h = 0
- # 初始化鼠标缩放标志
- self.move_left_up_flag = False
- self.move_left_flag = False
- self.move_left_down_flag = False
- self.move_up_flag = False
- self.move_down_flag = False
- self.move_right_up_flag = False
- self.move_right_flag = False
- self.move_right_down_flag = False
-
- # 设置边框圆角
- def paintEvent(self, event: PySide6.QtGui.QPaintEvent) -> None:
- painter = QPainter(self)
- painter.setRenderHint(QPainter.RenderHint.Antialiasing) # 设置抗锯齿,不然边框会有明显锯齿
- painter.setBrush(Qt.white) # 设置窗体颜色
- painter.drawRoundedRect(self.rect(), 10, 10)
- super().paintEvent(event)
-
- def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
- """
- @description 窗口缩放事件
- @param
- @return
- """
- # 最大化最小化的时候,需要去改变按钮组位置
- # self.titleBar.close_btn.move(self.width() - 33, 10)
- # self.titleBar.max_btn.move(self.width() - 66, 10)
- # self.titleBar.min_btn.move(self.width() - 99, 10)
- # self.titleBar.title.resize(self.width(), DEFAULT_TITILE_BAR_HEIGHT)
-
- # 记录鼠标移入的拖动区域,共8种区域
- self.left_up = QRect(0, 0, 10, 10)
- self.left = QRect(0, 10, 10, self.height() - 20)
- self.left_down = QRect(0, self.height() - 10, 10, 10)
- self.up = QRect(10, 0, self.width() - 20, 10)
- self.down = QRect(10, self.height() - 10, self.width() - 20, 10)
- self.right_up = QRect(self.width() - 10, 0, 10, 10)
- self.right = QRect(self.width() - 10, 10, 10, self.height() - 20)
- self.right_down = QRect(self.width() - 10, self.height() - 10, 10, 10)
-
- return super().resizeEvent(a0)
-
- def mousePressEvent(self, a0: QtGui.QMouseEvent) -> None:
- """
- 拖动窗口
- """
- if a0.button() == QtCore.Qt.LeftButton and self.isMaximized() == False and self.cursor().shape() == QtGui.QCursor(
- QtCore.Qt.ArrowCursor).shape():
- self.m_flag = True
- self.m_Position = a0.globalPosition().toPoint() - self.pos() # 获取鼠标相对窗口的位置
- a0.accept()
- self.setCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor)) # 更改鼠标图标
- else:
- """
- @description 鼠标按下事件
- @param
- @return
- """
- # 记录按下时窗口坐标, 这个用于窗口移动
- self.win_x = self.x()
- self.win_y = self.y()
- # 记录按下时鼠标坐标,这个用于计算鼠标移动的距离
- self.mouse_x = a0.globalPosition().x()
- self.mouse_y = a0.globalPosition().y()
- # 记录按下时窗口的大小,用于计算鼠标相对于窗口移动的距离,用于缩放
- self.win_w = self.width()
- self.win_h = self.height()
-
- if not self.isMaximized():
- # 如果按下的是鼠标左键
- if a0.button() == Qt.MouseButton.LeftButton and self.left_up.contains(a0.position().x(),
- a0.position().y()):
- self.move_left_up_flag = True
- if a0.button() == Qt.MouseButton.LeftButton and self.left.contains(a0.position().x(),
- a0.position().y()):
- self.move_left_flag = True
- if a0.button() == Qt.MouseButton.LeftButton and self.left_down.contains(
- a0.position().x(), a0.position().y()
- ):
- self.move_left_down_flag = True
- if a0.button() == Qt.MouseButton.LeftButton and self.up.contains(a0.position().x(), a0.position().y()):
- self.move_up_flag = True
- if a0.button() == Qt.MouseButton.LeftButton and self.down.contains(a0.position().x(),
- a0.position().y()):
- self.move_down_flag = True
- if a0.button() == Qt.MouseButton.LeftButton and self.right_up.contains(
- a0.position().x(), a0.position().y()
- ):
- self.move_right_up_flag = True
- if a0.button() == Qt.MouseButton.LeftButton and self.right.contains(a0.position().x(),
- a0.position().y()):
- self.move_right_flag = True
- if a0.button() == Qt.MouseButton.LeftButton and self.right_down.contains(
- a0.position().x(), a0.position().y()
- ):
- self.move_right_down_flag = True
- return super().mousePressEvent(a0)
-
- def mouseMoveEvent(self, a0: QtGui.QMouseEvent) -> None:
- """
- 拖动窗口
- """
- if QtCore.Qt.LeftButton and self.m_flag and self.cursor().shape() == QtGui.QCursor(
- QtCore.Qt.OpenHandCursor).shape():
- self.move(a0.globalPosition().toPoint() - self.m_Position) # 更改窗口位置
- a0.accept()
- else:
- """
- @description 鼠标按下移动事件
- @param
- @return
- """
- # 获取移动后鼠标的位置
- mouse_move_x = a0.globalPosition().x()
- mouse_move_y = a0.globalPosition().y()
- # 计算移动的距离
- offset_x = mouse_move_x - self.mouse_x
- offset_y = mouse_move_y - self.mouse_y
- # 移动鼠标时设置鼠标样式
- if not self.isMaximized():
- # 不是拖动的时才可能是缩放状态
- if not self.drag_flag:
- # 左上
- if self.left_up.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeFDiagCursor)
- # 左
- elif self.left.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeHorCursor)
- # 左下
- elif self.left_down.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeBDiagCursor)
- # 上
- elif self.up.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeVerCursor)
- # 下
- elif self.down.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeVerCursor)
- # 右上
- elif self.right_up.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeBDiagCursor)
- # 右
- elif self.right.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeHorCursor)
- # 右下
- elif self.right_down.contains(a0.position().x(), a0.position().y()):
- self.setCursor(Qt.SizeFDiagCursor)
- else:
- self.setCursor(Qt.ArrowCursor)
- else:
- self.setCursor(Qt.ArrowCursor)
- else:
- self.setCursor(Qt.ArrowCursor)
- # 如果按下且在左上角范围内则缩放(其他代码参考左上)
- if self.move_left_up_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeFDiagCursor)
- resize_w = self.win_w - offset_x
- resize_h = self.win_h - offset_y
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_w
- resize_h = self.MIN_WINDOW_HEIGHT if resize_h < self.MIN_WINDOW_HEIGHT else resize_h
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 设置窗口移动,需要鼠标跟随
- # x y 都要鼠标跟随
- if resize_w != self.MIN_WINDOW_WIDTH and resize_h != self.MIN_WINDOW_HEIGHT:
- self.move(self.win_x + offset_x, self.win_y + offset_y)
- # 缩放宽度等于最小宽度,高度鼠标跟随
- if resize_w == self.MIN_WINDOW_WIDTH and resize_h != self.MIN_WINDOW_HEIGHT:
- self.move(self.x(), self.win_y + offset_y)
- # 缩放高度等于最小高度,宽度鼠标跟随
- if resize_w != self.MIN_WINDOW_WIDTH and resize_h == self.MIN_WINDOW_HEIGHT:
- self.move(self.win_x + offset_x, self.y())
- # 如果按下且在左边范围内则缩放
- elif self.move_left_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeHorCursor)
- resize_w = self.win_w - offset_x
- resize_h = self.win_h
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_w
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 设置窗口移动,需要鼠标跟随
- # 只要宽度鼠标跟随
- if resize_w != self.MIN_WINDOW_WIDTH:
- self.move(self.win_x + offset_x, self.win_y)
- # 如果按下且在左下角范围内则缩放
- elif self.move_left_down_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeBDiagCursor)
- resize_w = self.win_w - offset_x
- resize_h = self.win_h + offset_y
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_w
- resize_h = self.MIN_WINDOW_HEIGHT if resize_h < self.MIN_WINDOW_HEIGHT else resize_h
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 设置窗口移动,需要鼠标跟随
- # x y 都要鼠标跟随
- if resize_w != self.MIN_WINDOW_WIDTH and resize_h != self.MIN_WINDOW_HEIGHT:
- self.move(self.win_x + offset_x, self.y())
- # 缩放高度等于最小高度,宽度鼠标跟随
- if resize_w != self.MIN_WINDOW_WIDTH and resize_h == self.MIN_WINDOW_HEIGHT:
- self.move(self.win_x + offset_x, self.y())
- # 如果按下且在上边范围内则缩放
- elif self.move_up_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeVerCursor)
- resize_w = self.win_w
- resize_h = self.win_h - offset_y
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_h = self.MIN_WINDOW_HEIGHT if resize_h < self.MIN_WINDOW_HEIGHT else resize_h
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 设置窗口移动,需要鼠标跟随
- # 只要高度鼠标跟随
- if resize_h != self.MIN_WINDOW_HEIGHT:
- self.move(self.win_x, self.win_y + offset_y)
- # 如果按下且在下边范围内则缩放
- elif self.move_down_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeVerCursor)
- resize_w = self.win_w
- resize_h = self.win_h + offset_y
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_h = self.MIN_WINDOW_HEIGHT if resize_h < self.MIN_WINDOW_HEIGHT else resize_h
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 如果按下且在右上角范围内则缩放
- elif self.move_right_up_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeBDiagCursor)
- resize_w = self.win_w + offset_x
- resize_h = self.win_h - offset_y
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_w
- resize_h = self.MIN_WINDOW_HEIGHT if resize_h < self.MIN_WINDOW_HEIGHT else resize_h
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 设置窗口移动,需要鼠标跟随
- # x y 都要鼠标跟随
- if resize_w != self.MIN_WINDOW_WIDTH and resize_h != self.MIN_WINDOW_HEIGHT:
- self.move(self.win_x, self.win_y + offset_y)
- # 缩放宽度等于最小宽度,高度鼠标跟随
- if resize_w == self.MIN_WINDOW_WIDTH and resize_h != self.MIN_WINDOW_HEIGHT:
- self.move(self.x(), self.win_y + offset_y)
- # 如果按下且在右边范围内则缩放
- elif self.move_right_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeHorCursor)
- resize_w = self.win_w + offset_x
- resize_h = self.win_h
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_w
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 如果按下且在右下角范围内则缩放
- elif self.move_right_down_flag:
- # 拖动的时候也要设置一下形状
- self.setCursor(Qt.SizeFDiagCursor)
- resize_w = self.win_w + offset_x
- resize_h = self.win_h + offset_y
- # 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了
- resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_w
- resize_h = self.MIN_WINDOW_HEIGHT if resize_h < self.MIN_WINDOW_HEIGHT else resize_h
- # 设置窗口缩放尺寸
- self.resize(resize_w, resize_h)
- # 如果按下才能移动
- elif self.drag_flag:
- # 设置窗口移动的距离
- self.move(self.win_x + offset_x, self.win_y + offset_y)
- return super().mouseMoveEvent(a0)
-
- def mouseReleaseEvent(self, a0: QtGui.QMouseEvent) -> None:
- self.m_flag = False
- self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
- """
- @description 鼠标按下松开事件
- @param
- @return
- """
- self.drag_flag = False
- self.move_left_up_flag = False
- self.move_left_flag = False
- self.move_left_down_flag = False
- self.move_up_flag = False
- self.move_down_flag = False
- self.move_right_up_flag = False
- self.move_right_flag = False
- self.move_right_down_flag = False
- self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
- return super().mouseReleaseEvent(a0)
- "1.0" encoding="UTF-8"?>
- <ui version="4.0">
- <class>Formclass>
- <widget class="QWidget" name="Form">
- <property name="geometry">
- <rect>
- <x>0x>
- <y>0y>
- <width>400width>
- <height>300height>
- rect>
- property>
- <property name="windowTitle">
- <string>Formstring>
- property>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QLineEdit" name="lineEdit"/>
- item>
- <item>
- <widget class="QPushButton" name="pushButton">
- <property name="text">
- <string>PushButtonstring>
- property>
- widget>
- item>
- layout>
- item>
- <item>
- <widget class="QTextEdit" name="textEdit"/>
- item>
- layout>
- item>
- layout>
- widget>
- <resources/>
- <connections/>
- ui>
- from PySide6.QtWidgets import QApplication, QWidget
-
- from custom_components import QWindowMoveResizeWidget, QCustomTitleBar
- from ui_widget_test import Ui_Form
-
-
- class TestWindow(QWindowMoveResizeWidget, Ui_Form):
- def __init__(self, parent=None):
- super(TestWindow, self).__init__(parent)
- self.setupUi(self)
- # 自定义标题栏
- QCustomTitleBar(self)
-
-
- if __name__ == "__main__":
- app = QApplication([])
- window = TestWindow()
- window.show()
- app.exec()

②QMainWindow使用示例
UI文件(转成py文件)
- "1.0" encoding="UTF-8"?>
- <ui version="4.0">
- <class>MainWindowclass>
- <widget class="QMainWindow" name="MainWindow">
- <property name="geometry">
- <rect>
- <x>0x>
- <y>0y>
- <width>641width>
- <height>444height>
- rect>
- property>
- <property name="windowTitle">
- <string>MainWindowstring>
- property>
- <widget class="QWidget" name="centralwidget">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QLineEdit" name="lineEdit"/>
- item>
- <item>
- <widget class="QPushButton" name="pushButton">
- <property name="text">
- <string>PushButtonstring>
- property>
- widget>
- item>
- layout>
- item>
- <item>
- <widget class="QTextEdit" name="textEdit"/>
- item>
- layout>
- item>
- layout>
- widget>
- <widget class="QMenuBar" name="menubar">
- <property name="geometry">
- <rect>
- <x>0x>
- <y>0y>
- <width>641width>
- <height>23height>
- rect>
- property>
- <widget class="QMenu" name="menu">
- <property name="title">
- <string>菜单string>
- property>
- widget>
- <addaction name="menu"/>
- widget>
- <widget class="QStatusBar" name="statusbar"/>
- widget>
- <resources/>
- <connections/>
- ui>
- from PySide6 import QtCore, QtGui
- from PySide6.QtWidgets import QApplication, QMainWindow
-
- from custom_components import QCustomTitleBar
- from ui_main_window_test import Ui_MainWindow
-
-
- class TestWindow(QMainWindow, Ui_MainWindow):
- def __init__(self, parent=None):
- super(TestWindow, self).__init__(parent)
- self.setupUi(self)
- # 自定义标题栏
- QCustomTitleBar(self)
-
- def mousePressEvent(self, event):
- if event.button() == QtCore.Qt.LeftButton and self.isMaximized() == False:
- self.m_flag = True
- self.m_Position = event.globalPosition().toPoint() - self.pos() # 获取鼠标相对窗口的位置
- event.accept()
- self.setCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor)) # 更改鼠标图标
-
- def mouseMoveEvent(self, mouse_event):
- if QtCore.Qt.LeftButton and self.m_flag:
- self.move(mouse_event.globalPosition().toPoint() - self.m_Position) # 更改窗口位置
- mouse_event.accept()
-
- def mouseReleaseEvent(self, mouse_event):
- self.m_flag = False
- self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
-
-
- if __name__ == "__main__":
- app = QApplication([])
- window = TestWindow()
- window.show()
- app.exec()
