The basic idea is run wxWidgets GUI in a single thread. This thread is managed by a manager. The manager stores a pointer of a wxApp and then it can call member of the wxApp to post event to update gui. In the manager class, an atomic_flag is used to ensure thread is correctly initialized.
So the GUI is running in a sub-thread and we are sending commands from main thread. This structure can be used for incorporating wxWidgets in a library.
main code:
Code: Select all
#include <iostream>
#include "libwx.hpp"
#include <thread>
int main()
{
GUIManager manager;
manager.init_gui_thread();
manager.update();
manager.clean();
}
Code: Select all
#pragma once
#include "wx/wx.h"
#include <thread>
#include <atomic>
wxDEFINE_EVENT(wxEVT_MY_UPDATE_UI, wxThreadEvent);
class myFrame : public wxFrame {
public:
myFrame() :wxFrame((wxFrame*)NULL, -1, "myFrame", wxPoint(50, 50), wxSize(800, 600)) {
Bind(wxEVT_MY_UPDATE_UI, &myFrame::updateUI, this);
};
void updateUI(wxThreadEvent& evt) {
wxStaticText* text = new wxStaticText(this, wxID_ANY, "Updated");
}
};
class TestApp : public wxApp {
public:
myFrame* frame;
bool OnInit() override {
frame = new myFrame;
frame->Show();
return true;
};
void add_static_text() {
wxThreadEvent evtcustom(wxEVT_MY_UPDATE_UI);
wxQueueEvent(frame, evtcustom.Clone());
};
};
struct GUIManager {
TestApp* app;
std::jthread* thread;
//Use a lock to ensure the gui thread is initialized only once.
std::atomic_flag lock;
GUIManager() {
app = new TestApp();
};
void init_gui_thread() {
if (lock.test()) {
return;
}
else {
thread = new std::jthread([this]() {
wxApp::SetInstance(app);
int argCount = 0;
char* argv[1];
wxEntryStart(argCount, argv);
wxTheApp->CallOnInit();
lock.test_and_set();
lock.notify_all();
wxTheApp->OnRun(); wxEntryCleanup();
});
};
};
void clean() {
if (lock.test()) {
thread->join();
};
};
void update() {
//If lock==false, then block until notified.
lock.wait(false);
app->add_static_text();
std::cout << "Update finished." << std::endl;
};
~GUIManager() {
delete thread;
}
};
Code: Select all
#include "libwx.hpp"
#include <iostream>
IMPLEMENT_APP_NO_MAIN(TestApp);