C++ 弹出对话框,将文件保存在单独的线程中
我有一个函数,当点击一个按钮时,它会在一个与主线程不同的线程中被调用,它调用C++ 弹出对话框,将文件保存在单独的线程中,c++,multithreading,qthread,qtscript,C++,Multithreading,Qthread,Qtscript,我有一个函数,当点击一个按钮时,它会在一个与主线程不同的线程中被调用,它调用QFileDialog::getSaveFileName()函数来获取用户保存的文件的文件句柄,但我不能在单独的线程中这样做,因为它会修改GUI,而您不允许这样做 如何解决此问题?QFileDialog::getSaveFileName()返回文件名,它既不尝试打开文件,也不返回文件句柄 您的问题并不清楚,但我假设您的按钮启动线程来执行一些冗长的任务,并将结果存储到文件中。因此,在按钮单击槽中调用QFileDialog:
QFileDialog::getSaveFileName()
函数来获取用户保存的文件的文件句柄,但我不能在单独的线程中这样做,因为它会修改GUI,而您不允许这样做
如何解决此问题?
QFileDialog::getSaveFileName()
返回文件名,它既不尝试打开文件,也不返回文件句柄
您的问题并不清楚,但我假设您的按钮启动线程来执行一些冗长的任务,并将结果存储到文件中。因此,在按钮单击槽中调用
QFileDialog::getSaveFileName()
,获取文件名并将该名称提供给线程。您的线程将只读取该文件名,因此可能不需要同步。然后,您只需在该非GUI线程中使用提供的文件名打开该文件。除了在创建另一个线程并将句柄作为参数传递之前从GUI线程中读取文件名和设计方面的注释外,我了解到,在某些情况下,您可能需要从其他线程调用GUI对话框
一种解决方案是从线程发出信号并在GUI中捕获。这种方法的缺点是可能很难得到结果(在您的案例中是文件名)
类似的解决方案是使用调用GUI线程中某个对象的方法,同时阻塞另一个线程,直到该方法返回
下一个示例使用辅助对象说明了这一点:
class FileDialogCaller : public QObject {
Q_OBJECT
public:
FileDialogCaller(QObject* parent = 0) : QObject(parent) {
// The helper object will live in the GUI thread
moveToThread(qApp->thread());
}
// Add the rest of parameters as needed
QString getSaveFileName(QWidget* parent, const QString& caption, const QString& dir,
const QString& filter) {
QString fileName;
if (QThread::currentThread() != qApp->thread()) { // no GUI thread
QMetaObject::invokeMethod(this, "getSaveFileName_", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QString, fileName),
Q_ARG(QWidget*, parent),
Q_ARG(QString, caption),
Q_ARG(QString, dir),
Q_ARG(QString, filter));
} else { // in GUI thread, direct call
fileName = getSaveFileName_(parent, caption, dir, filter);
}
return fileName;
}
private:
Q_INVOKABLE
QString getSaveFileName_(QWidget* parent, const QString& caption, const QString& dir,
const QString& filter) {
return QFileDialog::getSaveFileName(parent, caption, dir, filter);
}
};
使用它只是:
QString fileName = FileDialogCaller().getSaveFileName(nullptr, "Save", "", "Any (*.*)");
您可能需要检查
QThread::currentThread()!=qApp->thread()
在使用Qt::BlockingQueuedConnection之前。直接调用getSaveFileName.
即可case@Caleth当然可以这是假设OP方案,但我同意你的建议