【问题标题】:Missing menuBar in PyQt5PyQt5 中缺少菜单栏
【发布时间】:2017-01-27 04:45:43
【问题描述】:

我一直在使用 PyQt5 开发 GUI,并希望包含一个菜单栏。但是,当我编写此功能的代码时,我的菜单不会出现。弄清楚我对如何在 PyQt5 中实现菜单栏的理解不正确,我在网上寻找了一个预先存在的示例。经过一些调整,我开发了以下测试用例:

import sys
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenuBar, QAction, qApp

class Example(QMainWindow):

    def __init__(self):
        super().__init__()

        exitAction = QAction(QIcon('exit.png'), '&Exit', self)
        exitAction.triggered.connect(qApp.quit)

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&Testmenu')
        fileMenu.addAction(exitAction)

        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

但是,当我运行此程序时,找不到 Testmenu

在使用 pyuic5 将 .ui 文件转换为可导入的 .py 之前,我还尝试在 QTCreator 中创建菜单栏(以及我的 GUI 布局的其余部分)。我认为这会消除我的一些编程错误,但菜单栏仍然不会显示。有什么想法吗?

编辑:

我正在使用 Python 3.5 (Anaconda 4.1) 从 Jupyter 笔记本 4.1 版中运行此代码。我还在使用运行 os 10.1l、PyQt 5.7 和 Qt 版本 5.7.0 的 Macbook。

我已经意识到,如果我单击应用程序窗口然后单击返回窗口,菜单栏将变得响应 - 有效地取消焦点并聚焦应用程序。有了这些信息,我意识到我不是第一个注意到这个问题的人(参见https://github.com/robotology/yarp/issues/457)。不幸的是,我仍然不确定如何解决这个问题。

【问题讨论】:

  • @ekhumoro 我不明白这与我在 PyQt 中的问题有何关系。
  • 这几乎可以肯定是 osx 特有的问题。您的示例在 linux 上运行良好(也可能在 Windows 上)。自从menus seem to work differently on osx 以来,也许您应该准确地说明您希望看到什么,以及您实际得到什么。也许一些屏幕截图会有所帮助。您还应该说明您正在使用的 qt5/pyqt5 的确切版本。
  • 请说明您正在使用的 Qt 的确切版本,因为这几乎肯定是问题所在(而不是 PyQt)。
  • 一些类似的问题herehere

标签: python macos pyqt pyqt5 menubar


【解决方案1】:

在 MacOS 下,屏幕顶部会出现一个应用程序菜单。我设法让退出菜单选项出现在上面的示例中,方法是在字符串“Quit”前面加上一个空字符,如下所示:

close = QAction("\0Quit",self)
close.setShortcut("Ctrl+Q")
file.addAction(close)

macOS 似乎以某种方式拦截了名为“退出”或“退出”的菜单项。 您可以愉快地使用“关闭”或“离开”而无需解决方法。

【讨论】:

    【解决方案2】:

    菜单栏在 PyQt5 中不可见

    bar = self.menuBar()
    
    bar.setNativeMenuBar(False)
    
    file = bar.addMenu("File")
    
    file.addAction("New")
    

    NativeMenuBar 属性指定菜单栏是否应在支持它的平台上用作本机菜单栏。如果此属性为 true,则菜单栏在本机菜单栏中使用,并且不在其父级的窗口中,如果为 false,则菜单栏保留在窗口中。

    示例程序

    import sys
    
    from PyQt5.QtWidgets import QMainWindow, QAction, qApp, QApplication
    
    from PyQt5.QtGui import QIcon
    
    
    class Menu(QMainWindow):
    
        def __init__(self):
            super().__init__()
            self.initUI()
    
    
        def initUI(self):               
    
            exitAct = QAction(QIcon('exit.png'), ' &Quit', self)   
    
            exitAct.setShortcut('Ctrl+Q')
            exitAct.setStatusTip('Exit application')
            exitAct.triggered.connect(qApp.quit)
    
            self.statusBar()
    
            menubar = self.menuBar()
            menubar.setNativeMenuBar(False)
            fileMenu = menubar.addMenu('&File')
            fileMenu.addAction(exitAct)
    
            bar = self.menuBar()
            file = bar.addMenu("Edit")
            file.addAction("New")
    
            self.setGeometry(300, 300, 300, 200)
            self.setWindowTitle('Simple menu')    
            self.show()
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        ex = Menu()
        sys.exit(app.exec_())
    

    【讨论】:

      【解决方案3】:

      如果您的程序在 Ubuntu 上运行,您可能会在屏幕顶部找到菜单栏。

      如果要将菜单栏移动到窗口的标题栏,可以在“系统设置/外观/行为/显示窗口的菜单/在窗口的标题栏中”切换设置。

      【讨论】:

        【解决方案4】:

        这不是 Qt 和 PyQt5 的错误。

        我认为您的代码是zetcode pyqt5 menubar tutorial。我在 Mac OS 上遇到了完全相同的问题。

        第一个解决方案是一个技巧。使用' &Exit' 而不是'&Exit'。在'&Exit' 的开头插入一个空格,如下所示:

        ...
        # exitAction = QAction(QIcon('exit.png'), '&Exit', self) # Not shown
        exitAction = QAction(QIcon('exit.png'), ' &Exit', self)
        ...
        

        macOS 的系统级菜单栏保留了"Exit""Quit" 等关键字。出于同样的原因,yurisnm's example code 在 Mac OS 上仅显示除"Quit" 之外的菜单项。实际上“退出”有TextHeuristicRole,所以会覆盖应用程序菜单中的“退出”行为。当你点击“Python”菜单中的“退出python”时,它不会退出,只是打印“退出触发”。

        如果您必须在其他菜单中使用该名称(例如,文件、编辑),您需要像上面一样更改操作名称或使用 QAction::setMenuRole(...),如下所示:

        ...
        exitAction = QAction(QIcon('exit.png'), '&Exit', self)
        print(exitAction.menuRole()) # It prints "1". QAction::TextHeuristicRole
        exitAction.setMenuRole(QAction.NoRole)
        ...
        

        请阅读以下内容,这将对您有所帮助。

        【讨论】:

          【解决方案5】:

          您是否尝试过以下链接tutorialspoint中最简单的示例。

          这是最简单的例子。

          import sys
          
          from PyQt5.QtWidgets import QHBoxLayout, QAction, QApplication, QMainWindow
          
          class menudemo(QMainWindow):
              def __init__(self, parent = None):
                  super(menudemo, self).__init__(parent)
          
                  bar = self.menuBar()
                  file = bar.addMenu("File")
                  file.addAction("New")
          
                  save = QAction("Save",self)
                  save.setShortcut("Ctrl+S")
                  file.addAction(save)
          
                  edit = file.addMenu("Edit")
                  edit.addAction("copy")
                  edit.addAction("paste")
          
                  quit = QAction("Quit",self)
                  file.addAction(quit)
                  file.triggered[QAction].connect(self.processtrigger)
                  self.setWindowTitle("menu demo")
          
              def processtrigger(self, q):
                  print(q.text()+" is triggered")
          
          
          def main():
              app = QApplication(sys.argv)
              ex = menudemo()
              ex.show()
              sys.exit(app.exec_())
          
          if __name__ == '__main__':
              main()
          

          【讨论】:

          • 这个例子完美运行。我唯一的问题是它使用的是 PyQt4 而不是 PyQt5。我将导入更改为使用 PyQt5 并包含额外的行 from PyQt5.QtWidgets import * 认为该示例仍然有效。不幸的是,这个例子不适用于 PyQt5。我遇到了菜单栏会出现的相同问题,但单击它不会展开菜单。这个问题来自哪里的任何想法?
          • 先生,您只需要更改导入,因为从 PyQt5 开始,它们已经更改了一些路径。所以试试看.. [答案已更新]
          • 在尝试上述示例时,我已经将导入更改为使用 PyQt5。此示例中的窗口和菜单栏将加载,但除非我未聚焦然后聚焦窗口,否则菜单栏无响应。它似乎是 Mac OS X 上 Qt 或 PyQt 特有的问题
          • 我刚刚在 Linux 中尝试过,它工作得很好。我还取出了 QVBoxLayout,因为它甚至都不需要。我正在再次更新它,然后复制并过去看看它是否工作正常。如果不是,那肯定是 Mac OS X 的问题"(
          【解决方案6】:

          试试这个:

          menubar = QMenuBar()
          self.setMenuBar(menubar)
          

          而不是menubar = self.menuBar()

          【讨论】:

          • 啊没想到要找set方法。这让“Testmenu”显示在菜单栏中,但 exitAction 项仍然缺失。 fileMenu.addAction(exitAction) 不应该填充菜单吗?
          • 是的,它应该填充菜单。至少这是我在项目中的做法。一定有其他错误...你保留fileMenu = menubar.addMenu('&Testmenu')这行吗?
          • 是的,我保持原样。需要明确的是,当我运行代码时,会创建一个带有“遗嘱”菜单的菜单栏,但是当我单击它时没有任何反应。它几乎就像被冻结了一样,除了窗口本身(以及我机器上的所有其他东西)运行良好。
          • 我认为这可能与我正在使用 Jupiter Notebook 工作有关,但我只是从终端运行代码并出现了同样的问题。
          • 我在 PyQt5 和 PySide 上测试了您的原始代码,它们运行良好。你能告诉我们导入语句吗?
          猜你喜欢
          • 2021-01-10
          • 2017-10-29
          • 1970-01-01
          • 1970-01-01
          • 2021-05-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-23
          相关资源
          最近更新 更多