Problem:
(See sourcecode pieces of wxMSW)
wxApp::OnIdle()
Can only be entered once a time because of:
if ( s_inOnIdle )
return;
s_inOnIdle = TRUE;
ProcessPendingEvents();
...
s_inOnIdle = FALSE;
wxApp::MainLoop()
…
while ( m_keepGoing )
while ( !Pending() && ProcessIdle() )
;
DoMessage();
wxDialog::DoShowModal()
while ( IsModalShowing() )
while ( !wxTheApp->Pending() && wxTheApp->ProcessIdle() ) <<<<XXXX
wxTheApp->DoMessage();
Scenario:
-
Application calls wxPostEvent(Handler1,Event1)
-
Event1 is appended to the pending-events-list on Handler1
-
Handler 1 is appended to the wxPendingEvents list
-
wxApp.OnIdle() is called by the MainLoop() via ProcessIdle()
-
s_inOnIdle is set to True
-
EventHandler-Function of Event1 is called
-
Function does a ShowModal()
-
While modal-showing of Dialog, the ProcessIdle() function which invokes
wxApp.OnIdle has no effect because s_inOnIlde of wxTheApp is already set to true
and no Pending Events can be processed during a modal dialog shown
from a pending event!!!
Problem:
-
Implementation of wxDialog.ShowModal() under wxMSW does not work correctly,
when ShowModal called from an EventHandler invoked from a Pending Event
Questions:
-
How could this bug be fixed, does anybody have an idea?
-
How is wxGTKs ShowModal implemented?
-
Is there a workaround for my problem?
Please Help me somebody,
I would patch the ShowModal Implementation by myself, If somebody would give me a hint,
why the s_inOnIdle has to be done. if ( s_inOnIdle ) return;
Greetings, Andre’
See here a testscript:
···
from wxPython.wx import *
MYEVENT1=wxNewEventType()
MYEVENT2=wxNewEventType()
class Dialog2(wxDialog):
def init(self,parent):
wxDialog.init(self,parent,-1,“Dialog2”)
b=wxButton(self,-1,“Send Event2 to Dialog2”)
EVT_BUTTON(self,b.GetId(),self.onButton)
self.Connect(-1,-1,MYEVENT2,self.onEvent2)
self.Fit()
def onButton(self,event):
wxPostEvent(self,wxPyCommandEvent(MYEVENT2,self.GetId()))
print “Posted Event2 to Dialog2”
def onEvent2(self,event):
print “Received Event2 in Dialog2”
class Dialog1(wxDialog):
def init(self,parent):
wxDialog.init(self,parent,-1,“Dialog1”)
b1=wxButton(self,-1,“Dialog2.ShowModal() directly” ,pos=(0, 0))
b2=wxButton(self,-1,“Send Event to Dialog1 which Does Dialog2.ShowModal()”,pos=(0,30))
EVT_BUTTON(self,b1.GetId(),self.onOpenDirectly )
EVT_BUTTON(self,b2.GetId(),self.onPostEventToMySelf)
self.Connect(-1,-1,MYEVENT1,self.onEvent1)
self.SetSize((500,200))
def onOpenDirectly(self,event):
print “onOpenDirectly”
dialog2=Dialog2(self)
dialog2.ShowModal()
dialog2.Destroy()
def onPostEventToMySelf(self,event):
wxPostEvent(self,wxPyCommandEvent(MYEVENT1,self.GetId()))
print “Posted Event1 to Dialog1”
def onEvent1(self,event):
print “Received Event1 in Dialog1”
dialog2=Dialog2(self)
dialog2.ShowModal()
dialog2.Destroy()
class Application(wxApp):
def OnInit(self):
dialog1=Dialog1(None)
dialog1.ShowModal()
dialog1.Destroy()
return 1
app=Application()
app.MainLoop()