ShowModal-Problem innerhalb eines Threads

Plattformunabhängige GUIs mit wxWidgets.
Antworten
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Donnerstag 20. Januar 2005, 16:12

Hallo,

Wenn ich aus einem Thread heraus, einen Dialog mit ShowModal aufrufe, bleibt das Programm hängen und stürzt ab. Das passiert mit allen Dialogen außer mit dem wxMessageDialog.

Den Thread starte ich mit => thread.start_new_thread(...)

Wie kann ich das Problem lösen?
Gruß, Harry
Francesco_not_logged_in

Donnerstag 20. Januar 2005, 17:30

HarryH hat geschrieben:Hallo,

Wenn ich aus einem Thread heraus, einen Dialog mit ShowModal aufrufe, bleibt das Programm hängen und stürzt ab. Das passiert mit allen Dialogen außer mit dem wxMessageDialog.

Den Thread starte ich mit => thread.start_new_thread(...)

Wie kann ich das Problem lösen?
Innerhalb eines threads auf gui elemente zugreifen bringt Probleme mit sich.
Soweit ich mich erinnere, ist nur der wx.MessageDialog threadsafe.

Ich habe auch einmal dieses Problem gehabt, wobei mir in der wxPython-User list geraten wurde,
alle gui sachen im mainthread zu erledigen.
(Aus den worker threads mit wx.PostEvent an
den mainthread weiterposten).

Vielleicht auch hilfreich:

http://wiki.wxpython.org/index.cgi/LongRunningTasks
http://wiki.wxpython.org/index.cgi/WorkingWithThreads
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Freitag 21. Januar 2005, 08:40

Hallo Francesco,

Danke für deine Informationen.
Ich bin auch noch auf eine andere Lösung gekommen. Die Probleme treten nämlich nur auf, wenn ich mit ShowModal auf den Dialog zugreife, nicht bei Show. Allerdings sollte in meinem Fall die Anwendung warten.

Deswegen bin ich noch auf folgenden Lösung gekommen:

Code: Alles auswählen

def MakeModal(self):
        """ Makes the dialog modal inside a thread """
        thread.start_new_thread(self.Show,())
        while not self.IsShown():
            time.sleep(0.01)
        while self.IsShown():
            time.sleep(0.1)
Diese Methode füge ich zu dem Dialog hinzu, und rufe ihn damit auf.
MIt dem Thread innerhalb der Methode wird der Dialog angezeigt.
Die erste Schleife wartet bis der Dialog IsShown() ist und bricht dann ab. Die zweite Schleife wartet bis der Dialog geschlossen ist.
Evtl. könnte mann noch einen Returncode am Ende der Funktion eingeben.

Allerdings muss der Dialog außerhalb des Threads erzeugt werden!
Gruß, Harry
Francesco_not_logged_in

Freitag 21. Januar 2005, 10:29

HarryH hat geschrieben:Hallo Francesco,

Danke für deine Informationen.
Ich bin auch noch auf eine andere Lösung gekommen.
Hallo Harry,
bitte, bin leider auch kein profi und versuche selbst, threads zu vermeiden. :)

Gute Idee Deine Lösung.
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Montag 24. Januar 2005, 09:09

Francesco hat folgendes geschrieben:

Aus den worker threads mit wx.PostEvent an
den mainthread weiterposten
Wenn ich ein Event weiterposte und dann einen Dialog mit ShowModal aufrufe wird dann auch der Thread angehalten oder läuft er weiter?

Und könnte mir jemand zeigen wie das mit dem wx.PostEvent funktioniert?
Gruß, Harry
Francesco_not_logged_in

Montag 24. Januar 2005, 13:53

HarryH hat geschrieben:
Francesco hat folgendes geschrieben:

Aus den worker threads mit wx.PostEvent an
den mainthread weiterposten
Wenn ich ein Event weiterposte und dann einen Dialog mit ShowModal aufrufe wird dann auch der Thread angehalten oder läuft er weiter?

Und könnte mir jemand zeigen wie das mit dem wx.PostEvent funktioniert?

Hallo, habe einen alten code gefunden.
So habe ich das damals in etwa gemacht:

g_thread_event = threading.Event()

thread:
Globals.g_strTitle = _("Overwrite %s ?") % strFile
Globals.g_thread_event.clear()

event = wxCommandEvent ()
event.SetEventType (wxEVT_COMMAND_BUTTON_CLICKED)
event.SetId (19999)

pFrm = wxGetApp().GetFrame()
if(pFrm):
wxPostEvent(pFrm, event)

Globals.g_thread_event.wait ()
return Globals.g_nGuiResult

main:
EVT_BUTTON(self, 19999, self.OnOverwriteDlg)

def OnOverwriteDlg(self, event):
dlg = COverwriteDlg (self)
dlg.m_wndInfoLabel.SetLabel (Globals.g_strTitle)
Globals.g_nGuiResult = dlg.ShowModal()
Globals.g_thread_event.set ()
Antworten