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方案,但我同意你的建议