簡體   English   中英

如何在 pyqt5 中的 menuBar 中添加分隔符

[英]How to add separator to menuBar in pyqt5

主 window 帶菜單欄、工具欄和狀態欄

class TajirMWindow(QMainWindow):
    """Main Window."""
    def __init__(self, parent=None):
        """Initializer."""
        super().__init__(parent)
        self.setWindowTitle("Tajir/Home")
        self.resize(800, 400)
        self.centralWidget = QLabel("Hello, World")
        self.centralWidget.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self.setCentralWidget(self.centralWidget)
        self._createActions()
        self._connectActions()
        self._createMenuBar() #Menus
        self._createToolBars()#tools
'''
Menu Bar function
'''
    def _createMenuBar():
        menuBar = self.menuBar()
        fileMenu = menuBar.addMenu("&File")
        outilMenu = menuBar.addMenu("&Outils")
        menuBar.addSeparator()
        achatMenu = menuBar.addMenu("Bying")
        stockMenu = menuBar.addMenu("Stocks")
        menuBar.addSeparator()
        helpMenu = menuBar.addMenu("&Help")

當我運行代碼時沒有問題,但我沒有得到分隔符

QMenuBar 本身不支持分隔符。 它甚至不支持添加 QWidgetAction,因為它們顯示為空操作,並且它們的小部件從未實際顯示。

唯一的解決方案是創建一個具有唯一標識符的“假”動作,並使用 QProxyStyle 繞過動作的繪制:我們覆蓋sizeFromContents()以便當 QMenuBar 計算其動作的大小時,它會返回適當的寬度,並且drawControl()繪制一個顯示為 VLine 的假 QFrame(如 Designers 中的垂直分隔符)。

帶分隔符的菜單欄

重要提示:使用nativeMenuBar時,這在 MacOS 上不起作用

class MenuProxy(QtWidgets.QProxyStyle):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # create a fake frame that we'll use as a source for the separator
        self.fakeFrame = QtWidgets.QFrame(frameShape=QtWidgets.QFrame.VLine)

    def sizeFromContents(self, content, opt, size, widget=None):
        size = super().sizeFromContents(content, opt, size, widget)
        if (content == self.CT_MenuBarItem and 
            isinstance(widget, QtWidgets.QMenuBar) 
            and opt.text == '_'):
                # use the size hint of the frame to return the correct width
                size.setWidth(self.fakeFrame.sizeHint().width())
        return size

    def drawControl(self, ctl, opt, qp, widget=None):
        if (ctl == self.CE_MenuBarItem and 
            isinstance(widget, QtWidgets.QMenuBar) and
            opt.text == '_'):
                self.fakeFrame.resize(opt.rect.size())
                frameOpt = QtWidgets.QStyleOptionFrame()
                self.fakeFrame.initStyleOption(frameOpt)
                # the frame will be drawn using its own coordinates (starting 
                # from 0, 0), so we need to save the current state of the painter 
                # and then translate to the correct position
                qp.save()
                qp.translate(opt.rect.topLeft())
                # paint the "fake" frame
                self.drawControl(self.CE_ShapedFrame, frameOpt, qp, self.fakeFrame)
                # restore the painter to the previous position
                qp.restore()
                return
        super().drawControl(ctl, opt, qp, widget)


class YourWindow(QtWidgets.QMainWindow):
    def __init__(self):
        # ...
        sep = QtWidgets.QAction('_', self, enabled=False)
        menuBar.addAction(sep)
        # ...


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    app.setStyle(MenuProxy())

注意:

  • 由於 QMenuBar 自動忽略分隔符操作,setSeparator setSeparator(True)不能用於分隔符操作;
  • 必須禁用“分隔符”操作,否則鍵盤導航將嘗試聚焦它;
  • 這甚至適用於在 Designer 中創建的菜單欄,只要您添加一個以唯一標識符命名的菜單(該菜單應按照前一點的說明禁用);
  • '_'下划線用於標識樣式中的分隔符,因為 QStyle 無法直接訪問操作(因此我們不能使用action.setData ),並且需要使用特殊字符,因為某些 ZE8801102A40AD89DDCFCFDCAEBF008D25Z styles 有通過更改文本/標簽來設置助記符(用作快捷方式的下划線字母),所以如果你使用“分隔符”之類的東西,它可能會變成“&分隔符”,如果另一個 object 有“s”,它甚至可能變成“分隔符”快捷方式已被抓取,或者您添加了更多分隔符。 另一種可能性是使用 '&' 或 '&&&' 或任何其他唯一的非字母數字字符標識符,如'_#'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM