在 QSplitter 中最大化 QMdiSubWindow

Maximize QMdiSubWindow in QSplitter

我将 QSplitter 设置为中央小部件:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      mdiArea(new QMdiArea)
{
    QWidget *widget = new QWidget;
    widget->setMinimumSize(100, 100);

    QSplitter *splitter = new QSplitter;
    splitter->addWidget(mdiArea);
    splitter->addWidget(widget);

    setCentralWidget(splitter);

    createActions();
}

void MainWindow::createSubwin()
{
    QWidget *subwin = new QWidget(mdiArea);
    subwin->setWindowTitle("Subwindow");
    subwin->setMinimumSize(100, 100);
    mdiArea->addSubWindow(subwin);

    subwin->show();
}

void MainWindow::createActions()
{
    QAction *actSub = new QAction("Add subwindow", this);
    connect(actSub, SIGNAL(triggered()), SLOT(createSubwin()));

    QMenu *winMenu = menuBar()->addMenu("Windows");
    winMenu->addAction(actSub);
}

当我按下子window的最大化按钮时,子window覆盖了整个主window。有什么方法可以防止这种行为,让 subwindow 占据 QMdiArea 的所有 space 吗?

UPD:看起来只有当主 window 的 QMenuBar 中至少有一个菜单存在时才会出现问题。没有 menuBar 一切都按预期工作:

https://www.qtcentre.org/threads/44457-QMdiSubWindow-maximizing-problem

关于QSplitter,我给OP以下提示:

Move the right part of the QSplitter into a dock widget (and drop the QSplitter), so that the left part is the only part of the QMainWindow::centralWidget(). This would mean to work with the existing class instead of against, and is probably easier to manage.

OP 感谢停靠小部件的提示,但声称 sub-window 仍将占据整个主要 window。

我必须承认我缺乏MDI经验,并制作了一个MCVE来证明我自己是对还是错:

#include <QtWidgets>

// main application

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // setup GUI
  QMainWindow qWinMain;
  qWinMain.setWindowTitle("QMainWindow - MDI - Dock");
  qWinMain.resize(640, 480);
  // MDI
  QMdiArea qMDI;
  qWinMain.setCentralWidget(&qMDI);
  // MDI sub widget
  QLabel qWinSub("MDI Sub-Window\nwidget");
  qMDI.addSubWindow(&qWinSub);
  // Dock
  QDockWidget qDock;
  qDock.setWindowTitle("Dock");
  QLabel qLblDock("Dock\nwidget");
  qDock.setWidget(&qLblDock);
  qWinMain.addDockWidget(Qt::RightDockWidgetArea, &qDock);
  qWinMain.show();
  // runtime loop
  return app.exec();
}

输出:

所以,我无法复制 OP 的声明——它对我有效。

我的平台:Windows10、VS2019、Qt5.15


我稍微增强了第一个 MCVE,看看如果在 qWinMain.show() 之后创建 MDI sub-window 是如何工作的(通常情况下的预期)。

#include <QtWidgets>

// main application

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // setup GUI
  QMainWindow qWinMain;
  qWinMain.setWindowTitle("QMainWindow - MDI - Dock");
  qWinMain.resize(640, 480);
  // MDI
  QMdiArea qMDI;
  qWinMain.setCentralWidget(&qMDI);
  // Dock
  QDockWidget qWinDock;
  qWinDock.setWindowTitle("Dock");
  QWidget qDock;
  QVBoxLayout qVBoxDock;
  QPushButton qBtnNewMDISubWin("New Sub-Window");
  qVBoxDock.addWidget(&qBtnNewMDISubWin);
  qDock.setLayout(&qVBoxDock);
  qWinDock.setWidget(&qDock);
  qWinMain.addDockWidget(Qt::RightDockWidgetArea, &qWinDock);
  // create sub-window
  int i = 0;
  auto createSubWin = [&]() {
    ++i;
    QLabel* pQWinSub = new QLabel(QString("MDI Sub-Window\nwidget %1").arg(i));
    pQWinSub->setWindowTitle(QString("MDI Sub-Window %1").arg(i));
    qMDI.addSubWindow(pQWinSub);
    pQWinSub->show();
  };
  // install signal handlers
  QObject::connect(&qBtnNewMDISubWin, &QPushButton::clicked,
    createSubWin);
  // runtime loop
  qWinMain.show();
  return app.exec();
}

输出:

它在我这边仍然有效。

注:

我必须在 qMDI.addSubWindow(pQWinSub); 之后添加明确的 pQWinSub->show(); (这在第一个 MCVE 中不是必需的)。然而,这正是 OP 的代码所做的。


OP 回复:

It turns out that the problem occurs only when menuBar is present

哦哈。怎么来的?

我再次扩展了我的 MCVE,添加了一个菜单栏:

#include <QtWidgets>

// main application

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // setup GUI
  QMainWindow qWinMain;
  qWinMain.setWindowTitle("QMainWindow - MDI - Dock");
  qWinMain.resize(640, 480);
  // menu
  QMenuBar qMenuMain;
  QAction qCmdFile("File");
  QMenu qMenuFile;
  QAction qCmdFileNew("New");
  qMenuFile.addAction(&qCmdFileNew);
  qCmdFile.setMenu(&qMenuFile);
  qMenuMain.addAction(&qCmdFile);
  qWinMain.setMenuBar(&qMenuMain);
  // MDI
  QMdiArea qMDI;
  qWinMain.setCentralWidget(&qMDI);
  // Dock
  QDockWidget qWinDock;
  qWinDock.setWindowTitle("Dock");
  QWidget qDock;
  QVBoxLayout qVBoxDock;
  QPushButton qBtnNewMDISubWin("New Sub-Window");
  qVBoxDock.addWidget(&qBtnNewMDISubWin);
  qDock.setLayout(&qVBoxDock);
  qWinDock.setWidget(&qDock);
  qWinMain.addDockWidget(Qt::RightDockWidgetArea, &qWinDock);
  // create sub-window
  int i = 0;
  auto createSubWin = [&]() {
    ++i;
    QLabel* pQWinSub = new QLabel(QString("MDI Sub-Window\nwidget %1").arg(i));
    pQWinSub->setWindowTitle(QString("MDI Sub-Window %1").arg(i));
    pQWinSub->setFrameShape(QFrame::Box);
    qMDI.addSubWindow(pQWinSub);
    pQWinSub->show();
  };
  // install signal handlers
  QObject::connect(&qCmdFileNew, &QAction::triggered,
    createSubWin);
  QObject::connect(&qBtnNewMDISubWin, &QPushButton::clicked,
    createSubWin);
  // runtime loop
  qWinMain.show();
  return app.exec();
}

输出:

注:

我部分同意OP:

是的,现在最大化 MDI 的外观有点不同。看起来它占据了主 window 的整个客户区,但是…

…停靠小部件仍然可见。我在 QLabel(MDI sub-window 中的顶部小部件)中添加了一个框来说明这一点。事实上,sub-window 仍然只占据中央小部件(无论其标题栏的外观如何)。