Refresh wxDialog created from main thread event loop app
-
- Filthy Rich wx Solver
- Posts: 221
- Joined: Fri Jan 08, 2021 8:19 am
Refresh wxDialog created from main thread event loop app
Hi
I have an event main loop application which internally calls showModal() to show the wxDialog. The wxDialog() constructor creates a thread which runs in the background listing for some events. On these external events, we have to refresh our dialog.
Can you please let us know how this can be done?
Sample code:
Main Dll Application:
MyDllApp()
Dialog class:
class MyDialog : public wxDialog
{
MyDialog()
~MyDialog ()
}
MyDialog::MyDialog()
{
/* This creates a thread and waits for some third party events */
CreateThread(...,mythread(),..);
/* Show controls in the dialog */
}
mythread ()
{
/* wait for events */
/* On some specific event, we need to refresh the MyDialog() to show new controls */
}
Can you please help how to trigger some event to refresh the MyDialog() after showModel() is called from MainEventLoop?
Regards
Sridhar
I have an event main loop application which internally calls showModal() to show the wxDialog. The wxDialog() constructor creates a thread which runs in the background listing for some events. On these external events, we have to refresh our dialog.
Can you please let us know how this can be done?
Sample code:
Main Dll Application:
MyDllApp()
Dialog class:
class MyDialog : public wxDialog
{
MyDialog()
~MyDialog ()
}
MyDialog::MyDialog()
{
/* This creates a thread and waits for some third party events */
CreateThread(...,mythread(),..);
/* Show controls in the dialog */
}
mythread ()
{
/* wait for events */
/* On some specific event, we need to refresh the MyDialog() to show new controls */
}
Can you please help how to trigger some event to refresh the MyDialog() after showModel() is called from MainEventLoop?
Regards
Sridhar
Re: Refresh wxDialog created from main thread event loop app
Send a custom event to the dialog. https://docs.wxwidgets.org/trunk/overvi ... nts_customSridhar@Work wrote: ↑Fri Jan 21, 2022 2:28 pm I have an event main loop application which internally calls showModal() to show the wxDialog. The wxDialog() constructor creates a thread which runs in the background listing for some events. On these external events, we have to refresh our dialog.
Alternaively, you can use CallAfter() to call some code asynchronously from the main thread. https://docs.wxwidgets.org/trunk/classw ... 50b3719519
Use the source, Luke!
-
- Filthy Rich wx Solver
- Posts: 221
- Joined: Fri Jan 08, 2021 8:19 am
Re: Refresh wxDialog created from main thread event loop app
Thank you.
Do you have any sample code for reference?
Regards
Sridhar
Do you have any sample code for reference?
Regards
Sridhar
Re: Refresh wxDialog created from main thread event loop app
In its simplest form: Pass a MyDialog pointer to the thread constructor and store it in a member variable m_dialog;
Then, inside the thread you can call a method from the dialog.The code inside will be executed asynchronously from the context of the main thread.
Then, inside the thread you can call a method from the dialog.
Code: Select all
wxTheApp->CallAfter( [this] {
m_dialog->SomeMethod();
});
Use the source, Luke!
-
- Filthy Rich wx Solver
- Posts: 221
- Joined: Fri Jan 08, 2021 8:19 am
Re: Refresh wxDialog created from main thread event loop app
Thank you.
I'm actually launching a dialog from dll and then creating thread from dialog. So I don't think the below code would work.
However, I created a worker thread in dialog and then sending an OnThreadEvent() event to refresh the dialog.
The problem is the repaint is not clearing the old controls properly and creating the new controls. I can see that some old controls still appear in the new dialog created. Can you please let me know what is the correct way to call repaint on thread event in dialog code?
I tried Refresh() but it is not working as I show the dialog using ShowModel().
Regards
Sridhar
I'm actually launching a dialog from dll and then creating thread from dialog. So I don't think the below code would work.
However, I created a worker thread in dialog and then sending an OnThreadEvent() event to refresh the dialog.
The problem is the repaint is not clearing the old controls properly and creating the new controls. I can see that some old controls still appear in the new dialog created. Can you please let me know what is the correct way to call repaint on thread event in dialog code?
I tried Refresh() but it is not working as I show the dialog using ShowModel().
Regards
Sridhar
Re: Refresh wxDialog created from main thread event loop app
Are you sure this is a refresh/redraw issue? Does the dialog "fix" itself when you resize it, or force a refresh by dragging another window across?
Use the source, Luke!
-
- Filthy Rich wx Solver
- Posts: 221
- Joined: Fri Jan 08, 2021 8:19 am
Re: Refresh wxDialog created from main thread event loop app
Hi
Yes,
When I call ShowModel(), it calls the dialog constructor which internally draws the controls and the layout of the dialog.
When I get the thread events occur1, I show a different layout with different controls and dialog increases in size or decreases in size.
However, the new dialog layout is not clean. It shows some borders/colors of previous dialog/layout.
I'm redrawing the controls and then running the below functions.
Update();
Refresh();
Let me know if I have to do anything extra?
Regards
Sridhar
Yes,
When I call ShowModel(), it calls the dialog constructor which internally draws the controls and the layout of the dialog.
When I get the thread events occur1, I show a different layout with different controls and dialog increases in size or decreases in size.
However, the new dialog layout is not clean. It shows some borders/colors of previous dialog/layout.
I'm redrawing the controls and then running the below functions.
Update();
Refresh();
Let me know if I have to do anything extra?
Regards
Sridhar
Re: Refresh wxDialog created from main thread event loop app
You didn't answer my question:
Does the dialog "fix" itself when you resize it, or force a refresh by dragging another window across?
The order of these two is wrong, but i don't think it will make a difference in this case.
Use the source, Luke!
-
- Filthy Rich wx Solver
- Posts: 221
- Joined: Fri Jan 08, 2021 8:19 am
Re: Refresh wxDialog created from main thread event loop app
>>Does the dialog "fix" itself when you resize it, or force a refresh by dragging another window across?
No. It doesn't.
Thank you.
No. It doesn't.
Thank you.
Re: Refresh wxDialog created from main thread event loop app
Ok, then it's not a layout/redraw issue, but something more serious.
How are you deleting the previous content? Can you show some code?
How are you deleting the previous content? Can you show some code?
Use the source, Luke!
-
- Filthy Rich wx Solver
- Posts: 221
- Joined: Fri Jan 08, 2021 8:19 am
Re: Refresh wxDialog created from main thread event loop app
Sample code:
Hi
Please find the sample code below.
As you can see, the MyDialog application is first created with funtion ShowLayoutandControls_Type1().
Onthreadevent, it is not deleting the layout but calling ShowLayoutandControls_Type2() followed with Update();Refresh().
Let me know if something what needs to be corrected to make it work correct. I want the previous layout to clear and the show the new layout controls on it.
Note: I'm not deleted the previous layout e.g. mainLayout object is not deleted.
Regards
Sridhar
Code: Select all
class MyThread : public wxThread
{
MyThread(wxEvtHandler* sink) : wxThread(wxTHREAD_JOINABLE), m_sink(sink)
{}
ExitCode Entry() override;
}
class MyDialog : public wxDialog
{
MyDialog( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE );
~MyDialog();
void OnThreadEvent(wxThreadEvent& evt)
{
ShowLayoutandControls_Type3();
Update();
Refresh();
}
}
MyDialog::MyDialog( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE )
{
/* Bind the OnThreadEvent with the dialog */
Bind(wxEVT_THREAD, &MyDialog::OnThreadEvent, this);
/* Start the thread */
StartMyThread();
/* Show default layout */
ShowLayoutandControls_Type1();
}
MyDialog::ShowLayoutandControls_Type1()
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
this->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) );
this->SetBackgroundColour( wxColour( 255, 255, 255 ) );
wxFlexGridSizer* mainLayout;
....
/* Add controls and layout with different layout dimensions */
this->SetSizer( mainLayout );
this->Layout();
mainLayout->Fit( this );
}
MyDialog::ShowLayoutandControls_Type2()
{
...
wxFlexGridSizer* mainLayout;
....
/* Add controls and layout with different layout dimensions */
this->SetSizer( mainLayout );
this->Layout();
mainLayout->Fit( this );
}
MyDialog::ShowLayoutandControls_Type3()
{
...
wxFlexGridSizer* mainLayout;
....
/* Add controls and layout */
this->SetSizer( mainLayout );
this->Layout();
mainLayout->Fit( this );
}
wxThread::ExitCode MyThread::Entry()
{
...
/* runs in loop waiting for events */
if(statuschanged) {
/* Send event */
wxThreadEvent evt;
evt.SetInt(++eventCount);
wxQueueEvent(m_sink, evt.Clone());
}
}
Main Dll application:
MyDialog *custom = new MyDialog();
ret = custom->ShowModal();
/* End Dialog */
Hi
Please find the sample code below.
As you can see, the MyDialog application is first created with funtion ShowLayoutandControls_Type1().
Onthreadevent, it is not deleting the layout but calling ShowLayoutandControls_Type2() followed with Update();Refresh().
Let me know if something what needs to be corrected to make it work correct. I want the previous layout to clear and the show the new layout controls on it.
Note: I'm not deleted the previous layout e.g. mainLayout object is not deleted.
Regards
Sridhar
Last edited by doublemax on Tue Feb 01, 2022 10:38 am, edited 1 time in total.
Reason: Added code tags
Reason: Added code tags
Re: Refresh wxDialog created from main thread event loop app
As you're not deleting the old controls, the result is not surprising.
Do you replace all controls or only a subset? If all controls get replaced, call DestroyChildren() before creating a new layout.
If you replace only a subset, put all "dynamic" controls onto a dedicated wxPanel. On layout change, call DestroyChildren() on that panel only.
Another option is to create all 3 layouts at once on separate wxPanels. Then put them into a wxSimpleBook which you can use to switch between them.
Do you replace all controls or only a subset? If all controls get replaced, call DestroyChildren() before creating a new layout.
If you replace only a subset, put all "dynamic" controls onto a dedicated wxPanel. On layout change, call DestroyChildren() on that panel only.
Another option is to create all 3 layouts at once on separate wxPanels. Then put them into a wxSimpleBook which you can use to switch between them.
Use the source, Luke!
-
- Filthy Rich wx Solver
- Posts: 221
- Joined: Fri Jan 08, 2021 8:19 am
Re: Refresh wxDialog created from main thread event loop app
Thank you.
I tried the following code to clear the old controls and show new controls. It works fine.
This is called before showing the new controls layout.
{{{
GetSizer()->Clear(true);
SetSizer(NULL, true);
}}}
Do you suggest above? or DestroyChildren()?
Regards
Sridhar
I tried the following code to clear the old controls and show new controls. It works fine.
This is called before showing the new controls layout.
{{{
GetSizer()->Clear(true);
SetSizer(NULL, true);
}}}
Do you suggest above? or DestroyChildren()?
Regards
Sridhar
-
- Filthy Rich wx Solver
- Posts: 221
- Joined: Fri Jan 08, 2021 8:19 am
Re: Refresh wxDialog created from main thread event loop app
Hi
What is the best way to gracefully terminate the infinite loop thread?
I'm using
void StopMyThread()
{
if ( m_thread )
{
m_thread->Delete();
wxDELETE(m_thread);
}
}
This is causing the application to crash/hang. This is being called on dialog destructor class.
Regards
SRidhar
What is the best way to gracefully terminate the infinite loop thread?
I'm using
void StopMyThread()
{
if ( m_thread )
{
m_thread->Delete();
wxDELETE(m_thread);
}
}
This is causing the application to crash/hang. This is being called on dialog destructor class.
Regards
SRidhar
Re: Refresh wxDialog created from main thread event loop app
Code: Select all
GetSizer()->Clear(true);
SetSizer(NULL, true);
Code: Select all
void StopMyThread()
{
if ( m_thread )
{
m_thread->Delete();
wxDELETE(m_thread);
}
}
Use the source, Luke!