Q对话框作为QMainWindow中的中心小部件布局



您能在Python中将QDialog显示为QMainWindow的中心小部件吗?如果是,你会怎么做?据我所知,我正在努力寻找添加菜单栏的最简单方法,该菜单栏仅适用于QMainWindow。有可能把两者联系在一起吗?

tl;dr

不可以,但您可以使用setMenuBar()将菜单栏添加到QDialog的布局集,甚至可以像添加任何其他小部件一样添加菜单栏,只需在";顶部";这种布局。

有可能吗

技术的答案是";是":由于QDialog是一个QWidget,您可以像使用任何其他QWidget子类一样使用setCentralWidget()

真正的答案是">:不要这么做&";。

QDialog与QMainWindow一样,旨在成为顶级小部件(也称为"窗口"(,因此它不应被添加为小部件的子级或布局。

很少有例外:

  • 当使用旨在尽可能";容器";的窗口,它们是:
    • QMdiArea
    • 图形视图框架
  • 在非常特殊的情况下(例如尝试dock窗口小部件的自定义布局(,您应该真正知道自己在做什么,真正意识到与用户体验相关的限制和方面

最重要的是,QDialog具有可能存在问题的特定标志和事件过滤器。

举个简单的例子:

mainWindow = QMainWindow()
dialog = QDialog()
layout = QVBoxLayout(dialog)
layout.addWidget(QPushButton())
mainWindow.setCentralWidget(dialog)
mainWindow.show()

现在,只需按Esc,就会看到对话框消失。

添加一个QDialog作为任何小部件的子级也会发生同样的情况,这显然意味着它不应该完成(除非使用上面列出的"容器"系统(。

这是YouTube上的一些教程应该被完全忽略的众多原因之一(因为它们提供了可怕的建议,比如在QStackedWidget中添加QMainWindow或QDialog(。

解决方案

实际上,它非常简单:只需将菜单栏添加到对话框的顶层布局中,就像对任何其他小部件所做的那样。

此外,考虑到所有的Qt布局管理器都继承了QLayout,QLayout有一个非常基本和重要的功能,但经常被忽视:setMenuBar()

告诉几何管理器将菜单栏小部件放置在parentWidget((的顶部,在QWidget::contentsMargins((外部。所有子窗口小部件都放置在菜单栏的底部边缘下方。

注意,这实际上是一个";便利性";并且它仅适用于";顶级";布局:如果您将菜单栏添加到嵌套布局中,则在整个大小提示/策略计算中不会考虑它,并且它可能会显示在上方(在z堆栈级别中(任何其他小部件上。

还要注意的是,由于显而易见的原因,设计器无法完成此操作。如果您在Designer中创建了一个QDialog,并且想要添加一个菜单栏,则必须通过代码来完成。

假设您在Designer:中为对话框正确设置了顶级布局(您应该一直这样做(

from myDialog import Ui_MyDialog
from PyQt5.QWidgets import *
class MyDialog(QDialog, Ui_MyDialog):
def __init__(self):
super().__init__()
self.setupUi(self)
self.menuBar = QMenuBar()
self.layout().setMenuBar(self.menuBar)
self.fileMenu = self.menuBar.addMenu('File')
self.someAction = self.fileMenu.addAction('Some action')

if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
dialog = MyDialog()
dialog.exec()