我有一个关于 QInputDialog 的问题。我在谷歌上度过了过去 3 天,并认为是时候在这里提问了,因为我找不到任何答案;
我的应用程序有一个主线程(在 Qt 中也称为 GUI 线程)。这个 GUI 线程创建了一个工作者。这是在不同的线程中运行的。该工作人员扫描文件夹。它还发送有关进度的 GUI 线程信息。工作正常。
现在问题来了。工作线程可能会遇到必须要求用户输入的情况。一个QString。在继续扫描剩余文件夹之前,它必须等待答案。但是,工作线程无法显示 QInputDialog 事实证明。只有 GUI 线程。
我也不能使用槽和信号,因为它们不能在 Qt 中返回值。我尝试使用插槽和引用的 QString,但有时会崩溃。我想不是线程安全的。
我尝试了 QMetaObject::invokeMethod 但也无法让它工作。另外,这甚至是线程安全的吗?
这里有人对此有解决方案吗?
如果有帮助,下面是我的代码,它已经“压缩”了,所以我不会浪费您的宝贵时间来熟悉我的变量名和实际内容。
初始代码(工作线程中的 QInputDialog) MainWindow.cpp
void MainWindow::worker_create(){
Worker* worker = new Worker;
QThread* thread = new QThread;
worker->moveToThread(thread);
connect(thread, SIGNAL(started()), worker, SLOT (start_work()));
connect(worker, SIGNAL(worker_status_changed(QByteArray)), ChanComObject, SLOT(worker_update(QByteArray)));
connect(worker, SIGNAL(finished(QString)), this, SLOT(worker_destroy(QString)));
connect(worker, SIGNAL(finished(QString)), worker, SLOT(deleteLater()));
connect(worker, SIGNAL(finished(QString)), thread, SLOT (quit()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
工人.cpp
Worker::ask(){
QStringList listToChooseFrom;
listToChooseFrom.append("A");
listToChooseFrom.append("B");
QString answer = QInputDialog::getItem(this, "Title", "Message", listToChooseFrom, 0, false, &ok);
return answer;
}
鬼鬼祟祟的参考代码(引用的 QString,有时会工作,有时会崩溃) 我尝试过的鬼鬼祟祟的参考技巧是这样的......首先在 MainWindow.cpp
void MainWindow::worker_create(){
// all other stuff from above, but an extra connect:
connect(worker, SIGNAL(worker_asks(Qstring*)), SLOT(gui_thread_dialog(QString*)));
}
void MainWindow::gui_thread_dialog(*sneakyReturnValue){
QString answer = QInputDialog::getItem(this, "Title", "Message", listToChooseFrom, 0, false, &ok);
*sneakyReturnValue = answer;
}
然后在工人..
Worker::ask(){
QString sneakyReturnValue;
emit worker_asks(*sneakyReturnValue);
return sneakyReturnValue;
}
INVOKEMETHOD代码(由于 parent() 无法使其工作,也不确定是否线程安全)
Q_INVOKABLE QString askUser();
..并在 MainWindow.cpp
QString MainWindow::askUser(){
QStringList listToChooseFrom;
listToChooseFrom.append("A");
listToChooseFrom.append("B");
return QInputDialog::getItem(this, "Title", "Message", listToChooseFrom, 0, false, &ok);
}
最后在 Worker.cpp
Worker::ask(){
QString dialogReturn;
QStringList listToChooseFrom;
listToChooseFrom.append("A");
listToChooseFrom.append("B");
bool u = QMetaObject::invokeMethod(parent,
"askUser",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QString, dialogReturn),
Q_ARG(QStringList, listToChooseFrom));
if(!u){ qDebug() << "invokeMethod failed"; }
result = dialogReturn;
}
但我无法获得对 GUI 线程工作的引用。invokeMethod 的第一个参数。父母不工作。我认为我的工人自动不是我的 GUI 线程的孩子。好吧, parent() 至少不起作用。