1

我一直在努力解决一个我自己无法解决的非常奇怪的行为,所以我在这里。

我正在为一个运行良好的控制台应用程序创建一个 GUI。用户可以选择要加载的文件或重新加载先前选择的文件。这两个动作由两个不同的slots. 我正在处理文件格式中的错误,exceptions它在控制台版本中运行良好,但对于 GUI,目前不太好......

当 openFile 中抛出错误时slot,该catch块使他的工作并且该方法按预期停止但是然后另一个插槽被意外调用。我不知道为什么,所以不知道如何纠正这种行为。

这是相关代码:

void Loader::openSourceFile()
{
    fileName = QFileDialog::getOpenFileName(myWindow, tr("Select source file"), QString(), tr("Text files (*.txt)"));
    try{
        parseSourceFile();
    } catch(MyException &e)
    {
        QString msg = QString(e.what());
        myWindow->alertUser(msg);
        return;
    }
}

void Loader::reloadSourceFile()
{
    try{
        parseSourceFile();
    } catch(MyException &e)
    {
        QString msg = QString(e.what());
        myWindow->alertUser(msg);
        return;
    }
}

使用环境:

myLoader = new Loader(this);
menuTop = menuBar()->addMenu(tr("&File"));

//open source file
openAction = new QAction(QIcon(":images/document.png"), tr("&Open"), this);
connect(openAction, SIGNAL(triggered()), myLoader, SLOT(openSourceFile()));
menuTop->addAction(openAction);

//reload source file
reloadAction = new QAction(QIcon(":images/reload.png"), tr("&Reload"), this);
connect(openAction, SIGNAL(triggered()), myLoader, SLOT(reloadSourceFile()));
menuTop->addAction(reloadAction);

注意:经过大量调试后,我发现该类的 moc 文件中的一个函数在执行 catch 块后被调用:

void Loader::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
    if (_c == QMetaObject::InvokeMetaMethod) {
        Q_ASSERT(staticMetaObject.cast(_o));
        Loader *_t = static_cast<Loader *>(_o);
        switch (_id) {
        case 0: _t->openSourceFile(); break;
        case 1: _t->reloadSourceFile(); break;
        default: ;
        }
    }
    Q_UNUSED(_a);
}

它用 _id = 1 调用,这解释了另一个插槽的意外执行。但是为什么会这样???有人可以解释如何避免这种情况吗?我已经让我自己的应用程序类派生qApplication并覆盖notify(),但这并没有改变任何东西。

4

1 回答 1

2

应该:

reloadAction = new QAction(QIcon(":images/reload.png"), tr("&Reload"), this);
connect(openAction, SIGNAL(triggered()), myLoader, SLOT(reloadSourceFile()));
menuTop->addAction(reloadAction);

是:

reloadAction = new QAction(QIcon(":images/reload.png"), tr("&Reload"), this);
connect(reloadAction, SIGNAL(triggered()), myLoader, SLOT(reloadSourceFile()));
//      ^^^^^^^^^^^^
menuTop->addAction(reloadAction);
于 2012-09-25T02:35:04.450 回答