我一直在努力应对一种我自己无法解决的奇怪行为,所以我在这里。
我正在为一个运行良好的控制台应用程序创建一个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);
注意:经过大量调试后,我发现在执行catch块后调用该类的moc文件中的一个函数:
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()
,但这不会改变任何内容。
答案 0 :(得分: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);