zhiyiYo / PyQt-Fluent-Widgets

A fluent design widgets library based on C++ Qt/PyQt/PySide. Make Qt Great Again.
https://qfluentwidgets.com
GNU General Public License v3.0
5.61k stars 541 forks source link

启用showMenuButton时,navigationInterface 的MenuButton错位。 #548

Closed kingmo888 closed 1 year ago

kingmo888 commented 1 year ago

image

self.navigationInterface = NavigationInterface(
            self, showMenuButton=True, showReturnButton=False)

当启用showMenuButton时,三等号按钮激活位置只在红框(下沿为分界线)下方了。红框下沿的上方,鼠标划过、点击无反应。

zhiyiYo commented 1 year ago

最小复现代码贴下

kingmo888 commented 1 year ago

最小复现代码贴下


import sys
from qframelesswindow import FramelessMainWindow, TitleBar
from qfluentwidgets import NavigationItemPosition, NavigationInterface
from qfluentwidgets import FluentIcon as FIF
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QFrame, QStackedWidget, QHBoxLayout, QLabel

class Widget(QFrame):
    def __init__(self, text: str, parent=None):
        super().__init__(parent=parent)
        self.setObjectName(text.replace(' ', '-'))
        self.label = QLabel(text, self)
        self.label.setAlignment(Qt.AlignCenter)
        self.hBoxLayout = QHBoxLayout(self)
        self.hBoxLayout.addWidget(self.label, 1, Qt.AlignCenter)

        # leave some space for title bar
        self.hBoxLayout.setContentsMargins(0, 32, 0, 0)

class CustomTitleBar(TitleBar):
    """ Title bar with icon and title """

    def __init__(self, parent):
        super().__init__(parent)
        # add window icon
        self.iconLabel = QLabel(self)
        self.iconLabel.setFixedSize(18, 18)
        self.hBoxLayout.insertSpacing(0, 10)
        self.hBoxLayout.insertWidget(1, self.iconLabel, 0, Qt.AlignLeft | Qt.AlignBottom)
        self.window().windowIconChanged.connect(self.setIcon)

        # add title label
        self.titleLabel = QLabel(self)
        self.hBoxLayout.insertWidget(2, self.titleLabel, 0, Qt.AlignLeft | Qt.AlignBottom)
        self.titleLabel.setObjectName('titleLabel')
        self.window().windowTitleChanged.connect(self.setTitle)

    def setTitle(self, title):
        self.titleLabel.setText(title)
        self.titleLabel.adjustSize()

    def setIcon(self, icon):
        self.iconLabel.setPixmap(QIcon(icon).pixmap(18, 18))

class MainWindow(FramelessMainWindow):
    def __init__(self):
        """"""
        super(MainWindow, self).__init__()
        self.setTitleBar(CustomTitleBar(self))

        widget = QtWidgets.QWidget()
        self.hBoxLayout = QHBoxLayout()
        widget.setLayout(self.hBoxLayout)
        self.setCentralWidget(widget)
        self.navigationInterface = NavigationInterface(
            self, showMenuButton=True, showReturnButton=False)
        self.stackWidget = QStackedWidget(self)

        self.initLayout()

        # create sub interface
        self.settingInterface = Widget('Setting Interface', self)

        self.stackWidget.addWidget(self.settingInterface)

        self.initNavigation()
        self.initWindow()

    def initWindow(self):
        self.resize(500, 600)
        self.setWindowIcon(QIcon('logo.png'))
        self.setWindowTitle('  PyQt-Fluent-Widgets')
        self.titleBar.setAttribute(Qt.WA_StyledBackground)

        desktop = QApplication.desktop().availableGeometry()
        w, h = desktop.width(), desktop.height()
        self.move(w//2 - self.width()//2, h//2 - self.height()//2)

    def initLayout(self):
        self.hBoxLayout.setSpacing(0)
        self.hBoxLayout.setContentsMargins(0, 0, 0, 0)
        self.hBoxLayout.addWidget(self.navigationInterface)
        self.hBoxLayout.addWidget(self.stackWidget)
        self.hBoxLayout.setStretchFactor(self.stackWidget, 1)

        self.titleBar.raise_()
        self.navigationInterface.displayModeChanged.connect(self.titleBar.raise_)

    def addSubInterface(self, w: QtWidgets.QWidget, icon, text, position=NavigationItemPosition.TOP):
        self.stackWidget.addWidget(w)
        self.navigationInterface.addItem(
            routeKey=w.objectName(),
            icon=icon,
            text=text,
            onClick=lambda: self.switchTo(w),
            position=position
        )

    def initNavigation(self):

        # add item to bottom
        self.addSubInterface(self.settingInterface, FIF.SETTING, 'Settings', NavigationItemPosition.BOTTOM)

        self.stackWidget.currentChanged.connect(self.onCurrentInterfaceChanged)
        self.stackWidget.setCurrentIndex(1)

    def switchTo(self, widget):
        self.stackWidget.setCurrentWidget(widget)

    def onCurrentInterfaceChanged(self, index):
        widget = self.stackWidget.widget(index)
        self.navigationInterface.setCurrentItem(widget.objectName())

if __name__ == '__main__':
    QApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
    QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
    QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)

    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    app.exec_()

其中,

        self.setWindowIcon(QIcon('logo.png'))
        self.setWindowTitle('  PyQt-Fluent-Widgets')

会导致位置重叠。

综合来说,猜测FramelessMainWindow基于QMainWindow,由于自身的layout,ICO、title位置会不准导致的? image

kingmo888 commented 1 year ago

@zhiyiYo 是否FramelessMainWindow下无法对其logo与title?谢谢。

zhiyiYo commented 1 year ago

你没给主界面的 hBoxLayout 设置顶部 margin,导致标题栏和导航栏按钮重叠了

zhiyiYo commented 1 year ago

或者你就重写主界面 resizeEvent,把标题栏往右移动 60px