Exemple #1
0
class FrameLessWindowUI(QWidget):
    """ 主窗口UI 无边框窗口的基本事件(放大缩小移动等)处理"""
    Left, Top, Right, Bottom, LeftTop, RightTop, LeftBottom, RightBottom = range(
        8)  # 枚举左上右下以及四个定点
    MARGIN = 5  # 边缘宽度小用于调整窗口大小

    def __init__(self, *args, **kwargs):
        super(FrameLessWindowUI, self).__init__(*args, **kwargs)
        main_layout = QVBoxLayout()
        main_layout.setContentsMargins(
            QMargins(self.MARGIN, self.MARGIN, self.MARGIN, self.MARGIN))
        main_layout.setSpacing(0)
        self.setWindowIcon(QIcon("media/logo.png"))
        self.setWindowTitle("分析决策系统")

        # 基本事件属性设置
        self.setMouseTracking(True)
        self._pressed = False
        self._direction = None
        self._mouse_pos = None

        self.title_bar = TitleBarUI(self)  # 窗口标题栏
        main_layout.addWidget(self.title_bar, alignment=Qt.AlignTop)

        self.navigation_bar = NavigationBar(self)  # 菜单和用户状态栏
        main_layout.addWidget(self.navigation_bar, alignment=Qt.AlignTop)

        self.center_widget = QMainWindow()  # 模块窗体显示窗口
        self.center_widget.setContentsMargins(QMargins(2, 0, 2, 2))
        main_layout.addWidget(self.center_widget)

        self.setLayout(main_layout)

        # 样式,属性,大小设置
        self.title_bar.installEventFilter(self)  # 安装事件过滤进入标题栏还原鼠标样式
        self.navigation_bar.installEventFilter(self)
        self.center_widget.installEventFilter(self)

        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowSystemMenuHint
                            | Qt.WindowMinimizeButtonHint
                            | Qt.WindowMaximizeButtonHint)

        available_size = QDesktopWidget().availableGeometry(
        )  # 用户的桌面信息,来改变自身窗体大小
        available_width, available_height = available_size.width(
        ), available_size.height()
        self.resize(available_width * 0.75, available_height * 0.8)
        self.setMaximumSize(available_width, available_height)  # 最大为用户桌面大小
        self.setMinimumSize(available_width * 0.5,
                            available_height * 0.5)  # 最小为用户桌面大小的一半
        self.setAttribute(Qt.WA_TranslucentBackground, True)  # 窗口透明
        self.center_widget.setAutoFillBackground(True)  # 被窗口透明影响,自动填充
        self.center_widget.setObjectName("centerWidget")
        self.setStyleSheet(
            "#centerWidget{background-color:rgb(255,255,255);border:2px solid rgb(34,102,175);border-top:none;"
            "border-bottom-right-radius:5px;border-bottom-left-radius:5px}")

    def eventFilter(self, obj, event):
        """ 事件过滤器, 用于解决鼠标进入其它控件后还原为标准鼠标样式 """
        if isinstance(event, QEnterEvent):
            self.setCursor(Qt.ArrowCursor)
            self._direction = None  # 去除方向
            self._pressed = None  # 去除按下标记
        return super(FrameLessWindowUI, self).eventFilter(obj, event)

    def mousePressEvent(self, event):
        """ 鼠标按下 """
        super(FrameLessWindowUI, self).mousePressEvent(event)
        if event.button() == Qt.LeftButton:
            self._mouse_pos = event.pos()
            self._pressed = True

    def mouseReleaseEvent(self, event):
        """ 鼠标弹起事件 """
        super(FrameLessWindowUI, self).mouseReleaseEvent(event)
        self._pressed = False
        self._direction = None

        # 鼠标移动事件(只有边框MARGIN大小范围有效果,因为其他的是其子控件)(会捕获子控件的鼠标按住移动的事件)

    def mouseMoveEvent(self, event):
        super(FrameLessWindowUI, self).mouseMoveEvent(event)
        pos = event.pos()
        pos_x, pos_y = pos.x(), pos.y()
        wm, hm = self.width() - self.MARGIN, self.height() - self.MARGIN
        # print(wm, hm)
        # 窗口最大无需事件
        if self.isMaximized() or self.isFullScreen():
            self._direction = None
            self.setCursor(Qt.ArrowCursor)
            return
        if event.buttons() == Qt.LeftButton and self._pressed:
            self.resize_window(pos)
        if pos_x <= self.MARGIN and pos_y <= self.MARGIN:
            # 左上角
            self._direction = self.LeftTop
            self.setCursor(Qt.SizeFDiagCursor)
        elif wm <= pos_x <= self.width() and hm <= pos_y <= self.height():
            # 右下角
            self._direction = self.RightBottom
            self.setCursor(Qt.SizeFDiagCursor)
        elif wm <= pos_x and pos_y <= self.MARGIN:
            # 右上角
            self._direction = self.RightTop
            self.setCursor(Qt.SizeBDiagCursor)
        elif pos_x <= self.MARGIN and hm <= pos_y:
            # 左下角
            self._direction = self.LeftBottom
            self.setCursor(Qt.SizeBDiagCursor)
        elif 0 <= pos_x <= self.MARGIN <= pos_y <= hm:
            # 左边
            self._direction = self.Left
            self.setCursor(Qt.SizeHorCursor)
        elif wm <= pos_x <= self.width() and self.MARGIN <= pos_y <= hm:
            # 右边
            self._direction = self.Right
            self.setCursor(Qt.SizeHorCursor)
        elif wm >= pos_x >= self.MARGIN >= pos_y >= 0:
            # 上面
            self._direction = self.Top
            self.setCursor(Qt.SizeVerCursor)
        elif self.MARGIN <= pos_x <= wm and hm <= pos_y <= self.height():
            # 下面
            self._direction = self.Bottom
            self.setCursor(Qt.SizeVerCursor)

    def paintEvent(self, event):
        """ 由于是全透明背景窗口,重绘事件中绘制透明度为1的难以发现的边框,用于调整窗口大小 """
        super(FrameLessWindowUI, self).paintEvent(event)
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setPen(QPen(QColor(255, 255, 255, 1), self.MARGIN * 2))
        painter.drawRect(self.rect())

    def resize_window(self, pos):
        """ 调整窗口大小 """
        if self._direction is None:
            return
        mpos = pos - self._mouse_pos
        xPos, yPos = mpos.x(), mpos.y()
        geometry = self.geometry()
        x, y, w, h = geometry.x(), geometry.y(), geometry.width(
        ), geometry.height()
        if self._direction == self.LeftTop:  # 左上角
            if w - xPos > self.minimumWidth():
                x += xPos
                w -= xPos
            if h - yPos > self.minimumHeight():
                y += yPos
                h -= yPos
        elif self._direction == self.RightBottom:  # 右下角
            if w + xPos > self.minimumWidth():
                w += xPos
                self._mouse_pos = pos
            if h + yPos > self.minimumHeight():
                h += yPos
                self._mouse_pos = pos
        elif self._direction == self.RightTop:  # 右上角
            if h - yPos > self.minimumHeight():
                y += yPos
                h -= yPos
            if w + xPos > self.minimumWidth():
                w += xPos
                self._mouse_pos.setX(pos.x())
        elif self._direction == self.LeftBottom:  # 左下角
            if w - xPos > self.minimumWidth():
                x += xPos
                w -= xPos
            if h + yPos > self.minimumHeight():
                h += yPos
                self._mouse_pos.setY(pos.y())
        elif self._direction == self.Left:  # 左边
            if w - xPos > self.minimumWidth():
                x += xPos
                w -= xPos
            else:
                return
        elif self._direction == self.Right:  # 右边
            if w + xPos > self.minimumWidth():
                w += xPos
                self._mouse_pos = pos
            else:
                return
        elif self._direction == self.Top:  # 上面
            if h - yPos > self.minimumHeight():
                y += yPos
                h -= yPos
            else:
                return
        elif self._direction == self.Bottom:  # 下面
            if h + yPos > self.minimumHeight():
                h += yPos
                self._mouse_pos = pos
            else:
                return
        self.setGeometry(x, y, w, h)

    def showMaximized(self):
        """ 窗口最大化去除边界MARGIN """
        super(FrameLessWindowUI, self).showMaximized()
        self.layout().setContentsMargins(0, 0, 0, 0)

    def showNormal(self):
        """ 还原保留调整大小的边界 """
        super(FrameLessWindowUI, self).showNormal()
        self.layout().setContentsMargins(self.MARGIN, self.MARGIN, self.MARGIN,
                                         self.MARGIN)
Exemple #2
0
 def __init__(self, w_window: QMainWindow) -> None:
     super().__init__(w_window)
     self._w_window = w_window  # Main Qt window.
     w_window.installEventFilter(self)