How to show modal-dialog without block mainGuiEventloop?

458 views
Skip to first unread message

krishnaLee

unread,
May 16, 2018, 10:11:29 PM5/16/18
to wx-u...@googlegroups.com
Hi,
For example, when I click a Start button,I will create a Modal Dialog to show progress,this Modal Dialog will close automatically by working thread event;

//follow is my failure test:
//follow code will create a Dialog but not modal
ThreadSnapshot* thread = new ThreadSnapshot(this); //ThreadSnapshot:public wxThread
dialogSnapshot = new DialogSnapshot(this);  //DialogSnapshot :public wxDialog
dialogSnapshot->Show();
thread->Run();

//follow change will create a modal Dialog,but it block main-event loop...
dialogSnapshot->ShowModal();
thread->Run();

thank you.
by krishna

Igor Korot

unread,
May 17, 2018, 12:26:44 AM5/17/18
to wx-u...@googlegroups.com
Hi

What is the context of the code above?
Can you post complete function?

Also accessing GUI from secondary thread is strongly discouraged. Please see the docs how to work with GUI from secondary thread.

Thank you.


thank you.
by krishna

--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.
 
To unsubscribe, send email to wx-users+u...@googlegroups.com
or visit http://groups.google.com/group/wx-users

krishnaLee

unread,
May 17, 2018, 1:23:18 AM5/17/18
to wx-u...@googlegroups.com
Hi Korot,
the context is eazy,it like wxwidget/samples/thread,
build this sample and run,click "start a worker thread "frome menu item"Thread"
it will show a modal dialog and show progress infomation,it's good.

but I want  a cumstom Dialog show my custom infomation,and remove the cancel button.

Of course I will not operate Main-GUI-resources in my thread,I will  also using wxQueueEvent to main frame. 

thank you 
by krishna.
To unsubscribe, send email to wx-users+unsub...@googlegroups.com
or visit http://groups.google.com/group/wx-users

Vadim Zeitlin

unread,
May 17, 2018, 9:55:52 AM5/17/18
to wx-u...@googlegroups.com
On Thu, 17 May 2018 10:11:05 +0800 (CST) krishnaLee wrote:

k> Hi,
k> For example, when I click a Start button,I will create a Modal Dialog to
k> show progress,this Modal Dialog will close automatically by working
k> thread event;
k>
k>
k> //follow is my failure test:
k> //follow code will create a Dialog but not modal
k> ThreadSnapshot* thread = new ThreadSnapshot(this); //ThreadSnapshot:public wxThread
k> dialogSnapshot = new DialogSnapshot(this); //DialogSnapshot :public wxDialog
k> dialogSnapshot->Show();
k> thread->Run();
k>
k>
k> //follow change will create a modal Dialog,but it block main-event loop...
k> dialogSnapshot->ShowModal();
k> thread->Run();

You do need to call ShowModal() to show the dialog modally. As it will
indeed block until it returns, you also must launch the thread before
calling it.

Other than that, you have the right approach: just post the events to the
main thread (which will be dispatched from inside ShowModal() to your event
handlers) and you can also use wxMessageQueue<> to send events to the
worker thread.

As usual, you need to pay attention to thread termination, this is
typically the trickiest part.

Good luck,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/

krishnaLee

unread,
May 17, 2018, 10:29:20 PM5/17/18
to wx-u...@googlegroups.com

Hi VZ,
I got it, follow is a my sample code,
I think we should be careful,when the dialog showd,the main gui-event loop is blocking.

//file1-3,main.cpp----------------------------------------------------------------
#include"wx/wx.h"
#include"MyFrame.h"
class MyApp :public wxApp
{
public:
bool OnInit()
{
wxFrame* frame = new MyFrame(NULL, -1, "title");
frame->Show();

return true;
}

};
wxIMPLEMENT_APP(MyApp);

//file2-3,MyFrame.h----------------------------------------------------------------------------------
#ifndef __MYFRAME_H__
#define __MYFRAME_H__

#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/string.h>
#include <wx/button.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/sizer.h>
#include <wx/frame.h>
#include <wx/stattext.h>
#include <wx/gauge.h>
#include <wx/dialog.h>

class MyDialog : public wxDialog
{
protected:
wxStaticText* mStaticText;
wxGauge* mGauge;
public:
MyDialog(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(396, 79), long style = wxDEFAULT_DIALOG_STYLE);
void setGaugeValue(int value);
void setText(wxString  str);
void onThreadEvent(wxThreadEvent& event);
~MyDialog();
};

class MyFrame : public wxFrame
{
protected:
wxButton* mButton;
void mButtonClick(wxCommandEvent& event);
public:
MyDialog* mDialog;
MyFrame(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(639, 300), long style = wxDEFAULT_FRAME_STYLE | wxTAB_TRAVERSAL);
~MyFrame();

};


class MyWorkThread :public wxThread
{
MyFrame* mFrame;
protected:
wxThread::ExitCode Entry();
public:
MyWorkThread(MyFrame* frame)
{
mFrame = frame;
}
};

#endif //__MYFRAME_H__

//file3-3,MyFrame.cpp----------------------------------------------------------------------------------
#include "MyFrame.h"

void MyFrame::mButtonClick(wxCommandEvent & event)
{
MyWorkThread* thread = new MyWorkThread(this);
thread->Run();
mDialog->ShowModal();
}

void MyDialog::onThreadEvent(wxThreadEvent & event)
{
int n = event.GetInt();
if (n >= 0)
{
//thread woring...
setGaugeValue(n);
}
else
{
if (n == -1)
{
//thread terminated normal;
this->EndModal(0);
setGaugeValue(0);
}
else
{
//thread error;
}
}
}

MyFrame::MyFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxFrame(parent, id, title, pos, size, style)
{
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
wxBoxSizer* bSizer1;
bSizer1 = new wxBoxSizer(wxVERTICAL);
mButton = new wxButton(this, wxID_ANY, wxT("test"), wxDefaultPosition, wxDefaultSize, 0);
bSizer1->Add(mButton, 0, wxALL, 5);
this->SetSizer(bSizer1);
this->Layout();
this->Centre(wxBOTH);

//the dialog;
mDialog = new MyDialog(this);
mDialog->setText("running...");

mButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MyFrame::mButtonClick), NULL, this);

}

MyFrame::~MyFrame()
{
mButton->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MyFrame::mButtonClick), NULL, this);
}

MyDialog::MyDialog(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxDialog(parent, id, title, pos, size, style)
{
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
wxBoxSizer* bSizer2;
bSizer2 = new wxBoxSizer(wxVERTICAL);

mStaticText = new wxStaticText(this, wxID_ANY, wxT("MyLabel"), wxDefaultPosition, wxDefaultSize, 0);
mStaticText->Wrap(-1);
bSizer2->Add(mStaticText, 0, wxALL, 5);

mGauge = new wxGauge(this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL);
mGauge->SetValue(0);
bSizer2->Add(mGauge, 0, wxALL | wxEXPAND, 5);


this->SetSizer(bSizer2);
this->Layout();
this->Connect(wxEVT_THREAD, wxThreadEventHandler(MyDialog::onThreadEvent), NULL, this);
this->Centre(wxBOTH);
}

void MyDialog::setGaugeValue(int value)
{
mGauge->SetValue(value);
}

void MyDialog::setText(wxString str)
{
mStaticText->SetLabel(str);
}

MyDialog::~MyDialog()
{
this->Disconnect(wxEVT_THREAD, wxThreadEventHandler(MyDialog::onThreadEvent), NULL, this);
}

wxThread::ExitCode MyWorkThread::Entry()
{
wxThreadEvent event(wxEVT_THREAD, -1);

wxMilliSleep(1000);
event.SetInt(30);
wxQueueEvent(mFrame->mDialog, event.Clone());

wxMilliSleep(1000);
event.SetInt(60);
wxQueueEvent(mFrame->mDialog, event.Clone());

wxMilliSleep(1000);
event.SetInt(100);
wxQueueEvent(mFrame->mDialog, event.Clone());

wxMilliSleep(1000);
event.SetInt(-1);
wxQueueEvent(mFrame->mDialog, event.Clone());

return 0;
}
//files-end

thank you very much;
by krishna.
Reply all
Reply to author
Forward
0 new messages