はい、非 GUI スレッドから GUI を使用できないことはわかっています。ただし、QWidget オブジェクトを作成し、それを GUI スレッドに送信してからシグナルを送信できるようにすることは合理的と思われます。ただし、そうしようとすると、ウィジェットを移動できないというエラーが表示されます。ただし、これは機能するようです:
#include <iostream>
#include <QApplication>
#include <QtConcurrentRun>
#include <QDialog>
class BasicViewer : public QDialog
{
Q_OBJECT
public:
void Function(const float a)
{
std::cout << a << std::endl;
}
};
struct BasicViewerWrapper : public QObject
{
Q_OBJECT
public:
BasicViewer WrappedBasicViewer;
void Function(const float a)
{
WrappedBasicViewer.Function(a);
}
};
#include "main.moc" // For CMake's automoc
void Function2()
{
BasicViewerWrapper basicViewerWrapper;
basicViewerWrapper.moveToThread(QCoreApplication::instance()->thread());
basicViewerWrapper.Function(2.0f);
}
void Function1()
{
Function2();
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QtConcurrent::run(Function1);
std::cout << "End" << std::endl;
return app.exec();
}
直接作成したい QWidget のインスタンスを格納する QWidget と同じ API を持つラッパー クラスを作成しました。そのラッパーを作成し、それを GUI スレッドに移動してから使用することが許可されています。私の質問は、このラッパーを書かなくてもこれを行う方法はありますか? それは非常に退屈に思えます。コンセプトは機能するので、直接実行できない理由がわかりません。何かご意見は?
- - - - - - 編集 - - - - - - - -
最初の例は悪い例でした。GUI 要素に対して何もしようとしなかったからです。この例では、実際に「別のスレッドにある親の子を作成できません」が生成されます。
#include <iostream>
#include <QApplication>
#include <QtConcurrentRun>
#include <QMessageBox>
class BasicViewer : public QMessageBox
{
Q_OBJECT
public:
};
struct BasicViewerWrapper : public QObject
{
Q_OBJECT
public:
BasicViewer WrappedBasicViewer;
void exec()
{
WrappedBasicViewer.exec();
}
};
#include "main.moc" // For CMake's automoc
void Function2()
{
BasicViewerWrapper basicViewerWrapper;
basicViewerWrapper.moveToThread(QCoreApplication::instance()->thread());
basicViewerWrapper.exec();
}
void Function1()
{
Function2();
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QtConcurrent::run(Function1);
return app.exec();
}
----------- 編集 2 ----------------
Wrapper のスレッドが移動された後にメンバー オブジェクトが作成されるため、これでうまくいくと思いました。
#include <iostream>
#include <QApplication>
#include <QtConcurrentRun>
#include <QMessageBox>
class BasicViewer : public QMessageBox
{
Q_OBJECT
public:
};
struct BasicViewerWrapper : public QObject
{
Q_OBJECT
public:
BasicViewer* WrappedBasicViewer;
void exec()
{
WrappedBasicViewer->exec();
}
void create()
{
WrappedBasicViewer = new BasicViewer;
}
};
#include "main.moc" // For CMake's automoc
void Function2()
{
BasicViewerWrapper basicViewerWrapper;
basicViewerWrapper.moveToThread(QCoreApplication::instance()->thread());
basicViewerWrapper.create();
basicViewerWrapper.exec();
}
void Function1()
{
Function2();
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QtConcurrent::run(Function1);
return app.exec();
}
残念ながら、そうではありません。誰でも理由を説明できますか?
--------------- 編集 3 --------------------
なぜこれが機能するのかわかりませんか?信号を使用して GUI コンポーネントをトリガーしますが、GUI オブジェクト (QDialog) は非 GUI スレッドでまだ作成されていませんか?
#include <iostream>
#include <QApplication>
#include <QtConcurrentRun>
#include <QMessageBox>
class DialogHandler : public QObject
{
Q_OBJECT
signals:
void MySignal(int* returnValue);
public:
DialogHandler()
{
connect( this, SIGNAL( MySignal(int*) ), this, SLOT(MySlot(int*)), Qt::BlockingQueuedConnection );
}
void EmitSignal(int* returnValue)
{
emit MySignal(returnValue);
}
public slots:
void MySlot(int* returnValue)
{
std::cout << "input: " << *returnValue << std::endl;
QMessageBox* dialog = new QMessageBox;
dialog->addButton(QMessageBox::Yes);
dialog->addButton(QMessageBox::No);
dialog->setText("Test Text");
dialog->exec();
int result = dialog->result();
if(result == QMessageBox::Yes)
{
*returnValue = 1;
}
else
{
*returnValue = 0;
}
delete dialog;
}
};
#include "main.moc" // For CMake's automoc
void MyFunction()
{
DialogHandler* dialogHandler = new DialogHandler;
dialogHandler->moveToThread(QCoreApplication::instance()->thread());
int returnValue = -1;
dialogHandler->EmitSignal(&returnValue);
std::cout << "returnValue: " << returnValue << std::endl;
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QtConcurrent::run(MyFunction);
std::cout << "End" << std::endl;
return app.exec();
}