前提:UI必須采用自适应布局。 

  1. 自定义组件【直接CV】custom_components.py

    # 自定义组件
    """
    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_sizereturn Noneelse: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 = 10self.MIN_WINDOW_HEIGHT = 10# 鼠标拖动窗口的标识self.m_flag = False# 初始化鼠标拖动标题栏标志self.drag_flag = False# 记录按下时窗口坐标, 这个用于窗口移动self.win_x = 0self.win_y = 0# 记录按下时鼠标坐标,这个用于计算鼠标移动的距离self.mouse_x = 0self.mouse_y = 0# 记录鼠标移入的拖动区域,共8种区域 左上 左 左下 上 下 右上 右 右下self.left_up = Noneself.left = Noneself.left_down = Noneself.up = Noneself.down = Noneself.right_up = Noneself.right = Noneself.right_down = None# 设置为True则mouseMoveEvent事件不需要按下也能触发,不然要按着鼠标左键或右键才能触发self.setMouseTracking(True)# 设置子类的mousetrack# self.centralwidget.setMouseTracking(True)# 记录按下时窗口的大小,用于计算鼠标相对于窗口移动的距离,用于缩放self.win_w = 0self.win_h = 0# 初始化鼠标缩放标志self.move_left_up_flag = Falseself.move_left_flag = Falseself.move_left_down_flag = Falseself.move_up_flag = Falseself.move_down_flag = Falseself.move_right_up_flag = Falseself.move_right_flag = Falseself.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 = Trueself.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 = Trueif a0.button() == Qt.MouseButton.LeftButton and self.left.contains(a0.position().x(),a0.position().y()):self.move_left_flag = Trueif a0.button() == Qt.MouseButton.LeftButton and self.left_down.contains(a0.position().x(), a0.position().y()):self.move_left_down_flag = Trueif a0.button() == Qt.MouseButton.LeftButton and self.up.contains(a0.position().x(), a0.position().y()):self.move_up_flag = Trueif a0.button() == Qt.MouseButton.LeftButton and self.down.contains(a0.position().x(),a0.position().y()):self.move_down_flag = Trueif a0.button() == Qt.MouseButton.LeftButton and self.right_up.contains(a0.position().x(), a0.position().y()):self.move_right_up_flag = Trueif a0.button() == Qt.MouseButton.LeftButton and self.right.contains(a0.position().x(),a0.position().y()):self.move_right_flag = Trueif a0.button() == Qt.MouseButton.LeftButton and self.right_down.contains(a0.position().x(), a0.position().y()):self.move_right_down_flag = Truereturn 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_xoffset_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_xresize_h = self.win_h - offset_y# 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_wresize_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_xresize_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_xresize_h = self.win_h + offset_y# 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_wresize_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_wresize_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_wresize_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_xresize_h = self.win_h - offset_y# 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_wresize_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_xresize_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_xresize_h = self.win_h + offset_y# 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_wresize_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 = Falseself.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))"""@description 鼠标按下松开事件@param@return"""self.drag_flag = Falseself.move_left_up_flag = Falseself.move_left_flag = Falseself.move_left_down_flag = Falseself.move_up_flag = Falseself.move_down_flag = Falseself.move_right_up_flag = Falseself.move_right_flag = Falseself.move_right_down_flag = Falseself.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 = 10self.MIN_WINDOW_HEIGHT = 10# 鼠标拖动窗口的标识self.m_flag = False# 初始化鼠标拖动标题栏标志self.drag_flag = False# 记录按下时窗口坐标, 这个用于窗口移动self.win_x = 0self.win_y = 0# 记录按下时鼠标坐标,这个用于计算鼠标移动的距离self.mouse_x = 0self.mouse_y = 0# 记录鼠标移入的拖动区域,共8种区域 左上 左 左下 上 下 右上 右 右下self.left_up = Noneself.left = Noneself.left_down = Noneself.up = Noneself.down = Noneself.right_up = Noneself.right = Noneself.right_down = None# 设置为True则mouseMoveEvent事件不需要按下也能触发,不然要按着鼠标左键或右键才能触发self.setMouseTracking(True)# 设置子类的mousetrack# self.centralwidget.setMouseTracking(True)# 记录按下时窗口的大小,用于计算鼠标相对于窗口移动的距离,用于缩放self.win_w = 0self.win_h = 0# 初始化鼠标缩放标志self.move_left_up_flag = Falseself.move_left_flag = Falseself.move_left_down_flag = Falseself.move_up_flag = Falseself.move_down_flag = Falseself.move_right_up_flag = Falseself.move_right_flag = Falseself.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 = Trueself.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 = Trueif a0.button() == Qt.MouseButton.LeftButton and self.left.contains(a0.position().x(),a0.position().y()):self.move_left_flag = Trueif a0.button() == Qt.MouseButton.LeftButton and self.left_down.contains(a0.position().x(), a0.position().y()):self.move_left_down_flag = Trueif a0.button() == Qt.MouseButton.LeftButton and self.up.contains(a0.position().x(), a0.position().y()):self.move_up_flag = Trueif a0.button() == Qt.MouseButton.LeftButton and self.down.contains(a0.position().x(),a0.position().y()):self.move_down_flag = Trueif a0.button() == Qt.MouseButton.LeftButton and self.right_up.contains(a0.position().x(), a0.position().y()):self.move_right_up_flag = Trueif a0.button() == Qt.MouseButton.LeftButton and self.right.contains(a0.position().x(),a0.position().y()):self.move_right_flag = Trueif a0.button() == Qt.MouseButton.LeftButton and self.right_down.contains(a0.position().x(), a0.position().y()):self.move_right_down_flag = Truereturn 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_xoffset_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_xresize_h = self.win_h - offset_y# 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_wresize_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_xresize_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_xresize_h = self.win_h + offset_y# 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_wresize_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_wresize_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_wresize_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_xresize_h = self.win_h - offset_y# 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_wresize_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_xresize_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_xresize_h = self.win_h + offset_y# 如果缩放后的尺寸小于最小尺寸则窗口不能缩放了resize_w = self.MIN_WINDOW_WIDTH if resize_w < self.MIN_WINDOW_WIDTH else resize_wresize_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 = Falseself.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))"""@description 鼠标按下松开事件@param@return"""self.drag_flag = Falseself.move_left_up_flag = Falseself.move_left_flag = Falseself.move_left_down_flag = Falseself.move_up_flag = Falseself.move_down_flag = Falseself.move_right_up_flag = Falseself.move_right_flag = Falseself.move_right_down_flag = Falseself.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))return super().mouseReleaseEvent(a0)
    
  2. 使用实例
    ①QWidget使用示例
    UI文件(转成py文件)

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0"><class>Form</class><widget class="QWidget" name="Form"><property name="geometry"><rect><x>0</x><y>0</y><width>400</width><height>300</height></rect></property><property name="windowTitle"><string>Form</string></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>PushButton</string></property></widget></item></layout></item><item><widget class="QTextEdit" name="textEdit"/></item></layout></item></layout></widget><resources/><connections/>
    </ui>
    
    from PySide6.QtWidgets import QApplication, QWidgetfrom custom_components import QWindowMoveResizeWidget, QCustomTitleBar
    from ui_widget_test import Ui_Formclass 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文件)

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0"><class>MainWindow</class><widget class="QMainWindow" name="MainWindow"><property name="geometry"><rect><x>0</x><y>0</y><width>641</width><height>444</height></rect></property><property name="windowTitle"><string>MainWindow</string></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>PushButton</string></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>0</x><y>0</y><width>641</width><height>23</height></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, QMainWindowfrom custom_components import QCustomTitleBar
    from ui_main_window_test import Ui_MainWindowclass 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 = Trueself.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 = Falseself.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))if __name__ == "__main__":app = QApplication([])window = TestWindow()window.show()app.exec()
    

Qt第二十七章:QWidget、QMainWindow无边框自定义标题栏并自由移动、缩放、圆角相关推荐

  1. 程序员编程艺术第二十七章:不改变正负数相对顺序重新排列数组(无解?)

    第二十七章:不改变正负数之间相对顺序重新排列数组.时间O(N),空间O(1) 前言 本文开始之前,顺道说个事:CSDN最近开始评选10大博客专栏,投票地址为:http://event.blog.csd ...

  2. spi收发时的寄存器sr不变_「正点原子Linux连载」第二十七章SPI实验(一)

    1)实验平台:正点原子Linux开发板 2)摘自<正点原子I.MX6U嵌入式Linux驱动开发指南> 关注官方微信号公众号,获取更多资料:正点原子 第二十七章SPI实验 同I2C一样,SP ...

  3. 【正点原子MP157连载】第二十七章 DHT11数字温湿度传感器实验-摘自【正点原子】STM32MP1 M4裸机CubeIDE开发指南

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  4. 【正点原子Linux连载】第二十七章 SPI实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

  5. SPI 读取不同长度 寄存器_正点原子Linux第二十七章SPI实验

    1)资料下载:点击资料即可下载 2)对正点原子Linux感兴趣的同学可以加群讨论:935446741 3)关注正点原子公众号,获取最新资料更新 第二十七章SPI实验 同I2C一样,SPI是很常用的通信 ...

  6. 【正点原子STM32连载】 第二十七章 RTC实时时钟实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

  7. 第二十七章:五姓七望

    第二十七章:五姓七望 现在皇宫外面送给李丽质的东西已经不少了,甚至已经相当的多了,都已经在屋内堆满了.不过李丽质还是继续堆着,因为李丽质知道,现在民心已经开始向着自己转变了. 他还时不时的想着,这李淳 ...

  8. 【正点原子FPGA连载】第二十七章DS18B20数字温度传感器实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1

    1)实验平台:正点原子新起点V2开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=609758951113 2)全套实验源码+手册+视频下载地址:ht ...

  9. 第二十七章 数论——快速幂与逆元

    第二十七章 快速幂与扩展欧几里德算法 一.快速幂 1.使用场景 2.算法思路 (1)二进制优化思想 (2)模运算法则 3.代码实现 (1)问题 (2)代码 二.快速幂求逆元 1.什么是逆元? (1)同 ...

最新文章

  1. CAS Server(一):搭建服务端
  2. 解决越狱后 SSH 不能连接的问题
  3. MIT Scheme 使用 Edwin
  4. 前端学习(3334):ant design中加入icon
  5. esmini接入外部ego车控制
  6. oracle data guard方案,Oracle Data Guard 概念篇
  7. 使用mysql索引的规则
  8. uva861 Little Bishops
  9. sim800c GPRS模块的透传模式
  10. day20---IO流概述
  11. Ubuntu下很给力的下载工具
  12. Java中Dom解析xml文档
  13. 知识点篇:7)企业标准体系制定要求
  14. VS2010 快捷键设置,快速编码1
  15. CSDN下载积分的获取方式
  16. MATLAB函数大全 .
  17. 做外贸可以开海外店铺吗?可以开哪些平台?
  18. unity 解决乱码_unity3d 中文乱码解决方法——cs代码文件格式批量转化UTF8
  19. 杂记1:正向反向迭代器,不同stl容器的lower_bound的使用(set,map,vector,arr,pair),数字转字符串
  20. 电影天堂APP项目开发之Python爬虫篇,共18课时/5时33分

热门文章

  1. 百度编辑器Ueditor1.4.3的使用
  2. 请对号入座,不会给洗地机电瓶充电的看这里
  3. Sharepoint构建轻量型应用之InfoPath的简单应用案例!
  4. 计算机网络 第二章、物理层
  5. 数据库BC范式(BCNF)判断和分解
  6. struts2类型日期类型转换器的bug
  7. 生鲜行业供应商管理系统加强产业链协同,实现供需双赢
  8. 深信服2022年春招内推
  9. 关于APS在企业生产计划上的应用
  10. Eplan使用过程中的知识点1