1

我需要一些建议来从 a访问 field( QString name) 变量。我正在构建某种安装程序,我想在单独的线程中进行安装工作。QWizardPageQThread

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

install 函数依赖于field()其他的许多变量QWizardPages。因此,我尝试从 QThread 执行此安装函数,该函数在我的QWizardPage. 问题是,field()-function ia 是非静态成员,因此它不起作用。所以我没有想法将我的安装功能与我的 WizardPage 并行运行。

我试过这样的事情:

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

我也愿意接受任何其他让我的安装程序工作的想法。也许有人知道我没有想到的事情。

4

1 回答 1

1

另一种方法是创建一个工作人员(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();
}
于 2019-08-11T01:41:50.447 回答