如何在QMainWindow中创建菜单栏

3
我正在使用PyQT编写一个小应用程序。我试图在应用程序顶部创建一个包含常见选项(“文件”,“编辑”,“选项”等)的菜单栏,但是当我尝试将其添加到我的QMainWindow类时,我的工具栏没有出现。我已经查看了周围,但我不知道我做错了什么。请注意,我已经尝试使用 QMainWindow.menuBar() 方法而不是创建 QToolbar ,但如果我这样做,则整个栏都不可见。使用下面的代码,即使它是空的,我至少得到了一个空栏。下面的代码是这个问题的最小示例。我想知道我必须更改什么才能显示操作。
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QBrush
from PyQt5.QtWidgets import QMainWindow, QGraphicsScene, QToolBar, QMenu, QAction, QGraphicsView, QApplication


class GraphWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.scene = QGraphicsScene()

        # a grid foreground
        self.scene.setBackgroundBrush(QBrush(Qt.lightGray, Qt.CrossPattern))
        self.grid = True

        # Create upper toolbar with menu options
        tb = QToolBar()
        menu = QMenu()
        db_action = QAction("Open file")
        db_action.setStatusTip("Select a file to use as a database")
        db_action.triggered.connect(self.open_new_db)
        menu.addAction(db_action)

        tb.addWidget(menu)
        tb.setAllowedAreas(Qt.TopToolBarArea)
        tb.setFloatable(False)
        tb.setMovable(False)
        self.addToolBar(tb)

        self.statusBar().showMessage("Ready")

        # Demonstrate the results from the input.

        graphics = QGraphicsView(self.scene)
        self.setCentralWidget(graphics)
        self.showFullScreen()

    def open_new_db(self):
        pass

    def keyPressEvent(self, e):
        # Currently, we respond to a press of the Escape key by closing the program.
        if e.key() == Qt.Key_Escape:
            self.close()

app = QApplication(sys.argv)
gr = GraphWindow()
sys.exit(app.exec_())

你使用的是哪个操作系统版本和QT版本?这可能是一个错误。 - Steve Lorimer
我使用 elementary OS 0.4.1 Loki 和 PyQT 5.9。 - Thalamus
2个回答

3
在菜单栏中创建菜单时,必须为其命名。此外,Qt不会接管菜单或操作,因此您必须为它们提供父级或以其他方式保留对它们的引用,以防止它们被垃圾回收。您可以按照以下方式修复示例:
class GraphWindow(QMainWindow):
    def __init__(self):
        ...
        # Create menu options
        menubar = self.menuBar()
        menu = QMenu('File', self) # title and parent
        db_action = QAction("Open file", self) # title and parent
        db_action.setStatusTip("Select a file to use as a database")
        db_action.triggered.connect(self.open_new_db)
        menu.addAction(db_action)
        menubar.addMenu(menu)

        self.statusBar().showMessage("Ready")

请注意,工具栏并不是必须的。一种更短、更简单的方法来实现相同的效果,是直接添加菜单和操作,如下所示:
    menubar = self.menuBar()
    menu = menubar.addMenu('File')
    db_action = menu.addAction("Open file")
    db_action.setStatusTip("Select a file to use as a database")
    db_action.triggered.connect(self.open_new_db)

在这里,Qt将会自动设置必要的父对象。


谢谢,这正是我所需要的。 - Thalamus

2
问题是由垃圾回收器引起的,变量仅在创建的上下文中保留,因为您在构造函数中创建了它,所以该python方法的结尾会将其删除。只有具有父级或是类成员的元素才能保留,因此在这个解决方案中使用第一种选项。
class GraphWindow(QMainWindow):
    def __init__(self):
        [...]
        # Create upper toolbar with menu options
        tb = QToolBar(self)
        menu = QMenu(self)
        db_action = QAction("Open file", self)
        db_action.setStatusTip("Select a file to use as a database")
        db_action.triggered.connect(self.open_new_db)
        menu.addAction(db_action)
        tb.addWidget(menu)
        tb.setAllowedAreas(Qt.TopToolBarArea)
        tb.setFloatable(False)
        tb.setMovable(False)
        self.addToolBar(tb)

        self.statusBar().showMessage("Ready")
        [...]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接