本文介绍了如何从std :: thread更改GUI?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我尝试使用 thread

中的 setVisible()

有一个事件:

  void MainWindow :: OnShow(){//开始OnShow动作ui-> LoadingBox-> setVisible(true);std :: thread dThread(OnShow_threaded,ui,&(this-> settingsMap));dThread.join();} 

有一个函数 OnShow_threaded :

  void OnShow_threaded(Ui :: MainWindow * ui,std :: unordered_map< QString,QString> * settingsMap){//连接到服务器bool hasInternet = false;//如果应用无法访问互联网->显示离线模式如果(!具有互联网){ui-> SettingsLabel-> setVisible(true);}} 

编译带有错误的静态程序集时,程序崩溃:

在线: ui-> SettingsLabel-> setVisible(true);

同时,动态链接时没有此类错误.

您可以在

以下是代码文件:

mainwindows.h

  #ifndef MAINWINDOW_H#define MAINWINDOW_H#include< QMainWindow>#include< QThread>命名空间Ui {类MainWindow;}类MainWindow:公共QMainWindow{Q_OBJECT上市:显式MainWindow(QWidget * parent = 0);〜MainWindow();信号:无效sigShowHide(bool);公共插槽:void onShowHideButtonThreaded(bool);void onButton1Click();私人的:Ui :: MainWindow * ui;};#endif//MAINWINDOW_H 

mainwindows.cpp

  #include"mainwindow.h";#include" ui_mainwindow.h"#include< QDebug>MainWindow :: MainWindow(QWidget * parent):QMainWindow(父级),ui(新的Ui :: MainWindow){ui-> setupUi(this);QObject :: connect(ui-> pushButton,& QPushButton :: clicked,this,& MainWindow :: onButton1Click);QObject :: connect(this,& MainWindow :: sigShowHide,this,& MainWindow :: onShowHideButtonThreaded);}MainWindow ::〜MainWindow(){删除ui;}无效MainWindow :: onShowHideButtonThreaded(bool a){qDebug()<<"主线程ID ="<<QThread :: currentThread()<<设置可见性";ui-> pushButton_2-> setVisible(a);}无效MainWindow :: onButton1Click(){qDebug()<<点击";qDebug()<<"主线程ID ="<<QThread :: currentThread();QThread * l_thread = QThread :: create([&](){qDebug()<<运行线程"<<QThread :: currentThreadId()<<"仅发射信号;发出sigShowHide(!this-> ui-> pushButton_2-> isVisible());});l_thread-> start();}` 

main.cpp

  #include"mainwindow.h";#include< QApplication>int main(int argc,char * argv []){QApplication a(argc,argv);MainWindow w;w.show();返回a.exec();} 

执行的一个例子是:

 主线程ID = QThread(0x116ee18)运行线程0x1ed8仅发出信号主线程ID = QThread(0x116ee18)设置可见性 

Firstly, I tried to use setVisible() from thread

There is an event:

void MainWindow::OnShow(){
    // Start OnShow actions
    ui->LoadingBox->setVisible(true);
    std::thread dThread(OnShow_threaded, ui, &(this->settingsMap));
    dThread.join();
}

There is a function OnShow_threaded:

void OnShow_threaded(Ui::MainWindow *ui, std::unordered_map<QString,QString> *settingsMap){

    // Connect to server
    bool hasInternet = false;

    // If app doesn't have Internet access -> show offline mode
    if (!hasInternet) {
        ui->SettingsLabel->setVisible(true);
    }
}

The program crashes when compiling a static assembly with an error:

On the line: ui->SettingsLabel->setVisible(true);

At the same time, there is no such error when linking dynamically.

You can find full project on GitHub


Secondly, I tried to use events.

There is a function OnShow_threaded:

void OnShow_threaded(MainWindow* mw, Ui::MainWindow *ui, std::unordered_map<QString,QString> *settingsMap){
    // Connect to server
    bool hasInternet = false;

    // If app doesn't have Internet access -> show offline mode
    if (!hasInternet) {
        MyEvent* event = new MyEvent(EventTypes::InternetConnectionError);
        QCoreApplication::postEvent(mw, event);
        //delete event;
        //delete receiver;
    }
}

There is an event class:

#ifndef EVENTS_HPP
#define EVENTS_HPP

#include <QEvent>
#include <QString>

enum EventTypes {
    InternetConnectionError,
    Unknown
};

class MyEvent : public QEvent
{
public:
  MyEvent(const EventTypes _type) : QEvent(QEvent::User) {_localType = _type;}
 ~MyEvent() {}

  auto localType() const {return _localType;}


private:
  int _localType;
};

#endif // EVENTS_HPP

There is an event handler:

void MainWindow::events(QEvent *event)
{
    if (event->type() == QEvent::User)
      {
        MyEvent* postedEvent = static_cast<MyEvent*>(event);

        if (postedEvent->localType() == EventTypes::InternetConnectionError){
            ui->WarningMsg->setVisible(true);
            ui->SettingsLabel->setVisible(true);
        }
    }
}

Passing parameters:

void MainWindow::OnShow(){
    // Start OnShow actions
    ui->LoadingBox->setVisible(true);
    std::thread dThread(OnShow_threaded, this, ui, &(this->settingsMap));
    dThread.detach();
}

There is a mainwindows hpp file:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
#include <QMovie>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QObject>
#include <QMessageBox>
#include <QStandardPaths>
#include <QDir>
#include <QFile>
#include <QCoreApplication>
#include <QSaveFile>
#include <QProcess>

#include <thread>
#include <chrono>
#include <unordered_map>
#include <iostream>
#include <fstream>
#include <cstdlib>

#include "settings.hpp"
#include "events.hpp"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void OnShow();

private slots:
    void SettingsLabelPressed();

    void on_CloseMsgButton_clicked();

    void on_Settings_SaveButton_clicked();

    void on_Settings_UseTranslation_stateChanged(int arg1);

protected:

    void events(QEvent* event);

private:
    Ui::MainWindow *ui;
    std::unordered_map<QString,QString> settingsMap;
};

void OnShow_threaded(MainWindow* mw, Ui::MainWindow *ui, std::unordered_map<QString,QString> *settingsMap);

#endif // MAINWINDOW_H

But event doesn't execute.
What did I do wrong?
And how to properly change the GUI from another thread?


З.Ы. Sorry for my English, I'm from Russia....


解决方案

As you asked for the demo with QThread, in the comments, then here it is.

As GUI, I have a mainwindow with two simple buttons and I want to show, hide the big buttons with a QThread (instead of just the slot clicked) I emit an intermediate signal from the clicked to hide/show the button.

The role of the QThreadis only to emit the signal to sigShowHide with argument trueor false.

The main UI thread treats this signal by showing or hiding the button by calling the slot onShowHideButtonThreaded which reacts to the signal sigShowHide

Here are the code files:

mainwindows.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QThread>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

signals:

       void sigShowHide(bool);

public slots:
       void onShowHideButtonThreaded(bool);
       void onButton1Click();


private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindows.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QObject::connect(ui->pushButton, &QPushButton::clicked, this, &MainWindow::onButton1Click);
    QObject::connect(this,&MainWindow::sigShowHide, this, &MainWindow::onShowHideButtonThreaded);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::onShowHideButtonThreaded(bool a)
{
    qDebug() << " the main thread id = " << QThread::currentThread() << "set the visibility ";
    ui->pushButton_2->setVisible(a);
}

void MainWindow::onButton1Click()
{
    qDebug()<< "clicked";
    qDebug() << " the main thread id = " << QThread::currentThread();
    QThread* l_thread = QThread::create([&]()
    {
        qDebug() << "Running Thread " << QThread::currentThreadId() << " to emit signal only ";
        emit sigShowHide( !this->ui->pushButton_2->isVisible());
    });
    l_thread->start();
  }

`

The main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

An example of execution is :

the main thread id = QThread(0x116ee18)
Running Thread 0x1ed8 to emit signal only
the main thread id = QThread(0x116ee18) set the visibility

这篇关于如何从std :: thread更改GUI?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 22:06