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:
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 0x0x36c56540. Receiver 'WarningMsg' (of type 'QGroupBox') was created in thread 0x0x341c2fa0", file kernel\qcoreapplication.cpp, line 558
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....