问题描述
首先,我尝试使用 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 QThread
is only to emit the signal to sigShowHide
with argument true
or 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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!