如何从 QWizardPage 和访问字段()运行 QThread

How to run a QThread from QWizardPage and access field()

本文关键字:运行 QThread 字段 访问 QWizardPage      更新时间:2023-10-16

我需要一些建议才能从QThread访问QWizardPage中的字段(QString name) 变量。我正在构建某种安装程序,我想在单独的线程中进行安装工作。

我的目的: 到达提交/安装页面时,我想执行代码来执行"安装"并使用我的进度更新QWizardPage,直到完成。

安装功能依赖于来自其他QWizardPages的许多field()变量。因此,我尝试从 QThread 执行此安装函数,该函数在我的QWizardPage的内部类中定义。问题是,field()函数 i 是一个非静态成员,因此它不起作用。所以我没有想法与我的向导页面并行运行我的安装功能。

我尝试了这样的事情:

InstallPage.h
class InstallPage : public QWizardPage
{
Q_OBJECT
class WorkerThread : public QThread
{
Q_OBJECT
void run() override;
};
public:
InstallPage(QWidget *parent = 0);
private: 
QLabel *lProgress;
WorkerThread *installer;
void install(); 
};

InstallPage.c
InstallPage::InstallPage(QWidget *parent)
: QWizardPage(parent)
{
...
installer = new WorkerThread(this);
installer->start();
}
void InstallPage::WorkerThread::run()
{
if(field("checkBox1").ToBool()) 
{
doStuff();
}
}
//QT-Creator says at field("checkBox1"): 
//error: call to non-static member function without an object argument

我也愿意接受任何其他想法,以使我的安装程序正常工作。也许有人知道一些我没有想到的事情。

另一种方法是创建一个工作线程 (QObject),该工作线程位于另一个线程中,该线程执行繁重的任务并通过信号通知该任务的状态:

#include <QtWidgets>
class InitialPage: public QWizardPage
{
public:
InitialPage(QWidget *parent = nullptr): QWizardPage(parent)
{
QSpinBox *spinbox = new QSpinBox;
QLineEdit *lineedit = new QLineEdit;
QVBoxLayout *lay = new QVBoxLayout(this);
lay->addWidget(spinbox);
lay->addWidget(lineedit);
registerField("value1", spinbox);
registerField("value2", lineedit);
}
};
class InstallWorker: public QObject
{
Q_OBJECT
public:
InstallWorker(QObject *parent=nullptr): QObject(parent)
{
}
public Q_SLOTS:
void install(int param1, const QString & param2)
{
Q_EMIT started();
for(int i=0; i < 100; i++){
qDebug() << __PRETTY_FUNCTION__ << i << param1 << param2;
QThread::msleep(100);
Q_EMIT progressChanged(i);
}
qDebug()<< __PRETTY_FUNCTION__ << "finished";
Q_EMIT finished();
}
Q_SIGNALS:
void started();
void progressChanged(int value);
void finished();
};
class InstallPage: public QWizardPage
{
Q_OBJECT
public:
InstallPage(QWidget *parent = nullptr): QWizardPage(parent),
label(new QLabel), progressbar(new QProgressBar)
{
QVBoxLayout *lay = new QVBoxLayout(this);
lay->addWidget(label);
lay->addWidget(progressbar);
progressbar->setMinimum(0);
progressbar->setMaximum(100);
thread = new QThread(this);
worker.moveToThread(thread);
connect(&worker, &InstallWorker::started, this, &InstallPage::onStarted);
connect(&worker, &InstallWorker::finished, this, &InstallPage::onFinished);
connect(&worker, &InstallWorker::progressChanged, this, &InstallPage::onProgressChanged);
thread->start();
}
~InstallPage(){
thread->quit();
thread->wait();
}
void initializePage(){
start_install();
}
private Q_SLOTS:
void start_install(){
int param1 = field("value1").toInt();; 
QString param2 = field("value2").toString();
QMetaObject::invokeMethod(&worker, "install", Qt::QueuedConnection, Q_ARG(int, param1), Q_ARG(QString, param2));
}
void onStarted(){
for(QWizard::WizardButton which: {QWizard::BackButton, QWizard::NextButton, QWizard::CancelButton})
if(QAbstractButton * button = wizard()->button(which))
button->setEnabled(false);
}
void onFinished(){
for(QWizard::WizardButton which: {QWizard::BackButton, QWizard::NextButton, QWizard::CancelButton})
if(QAbstractButton * button = wizard()->button(which))
button->setEnabled(true);
wizard()->next();
}
void onProgressChanged(int value){
progressbar->setValue(value);
label->setNum(value);
}
private:
InstallWorker worker;
QThread *thread;
QLabel *label;
QProgressBar *progressbar;
};
class FinalPage: public QWizardPage
{
public:
FinalPage(QWidget *parent = nullptr): QWizardPage(parent)
{
}
};
#include "main.moc"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QWizard wizard;
wizard.addPage(new InitialPage);
wizard.addPage(new InstallPage);
wizard.addPage(new FinalPage);
wizard.show();
return app.exec();
}