1

我正在编写一个带有典型主窗口 GUI 界面的程序,其中QMainWindowQt QMdiWindow5.4 类类似于下图之一(来自官方文档)。

Qt MDI

每次活动子窗口更改时,updateWindowMenu()都会调用该方法,并通过指向每个子窗口之一来清除并重新填充Window菜单QActions,也就是说,当您单击一个动作时,与该动作关联的子窗口将被带到前面,并将成为活动子窗口。关联已完成,QSignalMapper因为updateWindowMenu()需要当前活动的子窗口(如果有)。

当我单击一个动作时会出现问题,它的信号没有被触发,因此相关的子窗口没有被带到前面。经过调查,我意识到阻碍动作触发的是对menuWindow->removeAction(mySubwindowActions->at(n))(menuWindow来自.iu使用 Qt Designer 创建的文件的调用)。就是这样,如果我注释掉

// for (int n=0; n<mySubwindowActions->size(); ++n)
//    menuWindow->removeAction(mySubwindowActions->at(n));

Window每次调用时都会将重复的操作添加到菜单中updateWindowMenu(),但它们会按预期工作,并且会将关联的子窗口置于前面。

为什么会出现这种异常行为?如何在不妨碍新添加操作的正常工作的情况下删除操作?

WindowMain.h

class WindowMain : public QMainWindow, public Ui::mainWindow {
    Q_OBJECT

    private:
        QSignalMapper* mySignalMapper;
        QList<QAction*>* mySubwindowActions;

    private slots:
        void updateWindowMenu(QMdiSubWindow*);
        void setActiveSubWindow(QWidget*);
}

WindowMain.cpp

void WindowMain::WindowMain() {
    connect(myMdiArea, &QMdiArea::subWindowActivated, this, &WindowMain::updateWindowMenu);

    mySignalMapper = new QSignalMapper(this);
    connect(mySignalMapper, static_cast<void (QSignalMapper::*)(QWidget*)>(&QSignalMapper::mapped), this, &WindowMain::setActiveSubWindow);

    mySubwindowActions = new QList<QAction*>();
}


void WindowMain::updateWindowMenu(QMdiSubWindow* mdiSubwindow) {
    for (int n=0; n<mySubwindowActions->size(); ++n)
        menuWindow->removeAction(mySubwindowActions->at(n));
    mySubwindowActions->clear();

    if (mdiSubwindow != 0) {
        QList<QMdiSubWindow*> subwindows = myMdiArea->subWindowList();
        for (int n=0; n<subwindows.size(); ++n) {
            QAction* actionSubwindow = menuWindow->addAction(subwindows.at(n)->widget()->windowTitle());
            mySubwindowActions->append(actionSubwindow);
            mySignalMapper->setMapping(actionSubwindow, subwindows.at(n));
            connect(actionSubwindow, &QAction::triggered, mySignalMapper, static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map));
        }
    }
}


void WindowMain::setActiveSubWindow(QWidget* subWindow) {
    myMdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow*>(subWindow));
}
4

0 回答 0