Threading and multiple windows

I'm new to using wxPython (so please bear with me), but I'm having a
little trouble.
I'm writing a program which uses threads, and I want to have each
thread be able to create a window.
From what I understand, there can only be one app and one main loop
and the main loop doesn't return normally until its windows are
closed. So my problem is that if one thread adds a window and calls
MainLoop() so that the window is shown, then another thread in order
to add a window would need to exit and reenter the main loop, but this
kills all the windows that were open. Is there some way to add new
windows to an already running main loop without exiting and reentering
(or otherwise a way that preserves the old windows)?

At the moment, what each thread does when it is trying to open its
window is:

if self.app.IsMainLoopRunning():
    self.app.ExitMainLoop()
x=ReminderWin(self.message)
x.Show()
self.app.MainLoop()

self is the thread, self.app is the app the App, and ReminderWin is a
subclass of Frame which is what I want to be open.

Thanks,
-Taylor

Only do GUI calls from the main thread. Trying to open multiple windows from multiple threads will lead only to heartbreak and suffering. Put all the graphic stuff in the main thread, then set up some inter-thread communication for control.

Tom

···

On Wed, 2009-06-24 at 10:47 -0700, Taylor wrote:


I'm new to using wxPython (so please bear with me), but I'm having a
little trouble.
I'm writing a program which uses threads, and I want to have each
thread be able to create a window.
>From what I understand, there can only be one app and one main loop
and the main loop doesn't return normally until its windows are
closed. So my problem is that if one thread adds a window and calls
MainLoop() so that the window is shown, then another thread in order
to add a window would need to exit and reenter the main loop, but this
kills all the windows that were open. Is there some way to add new
windows to an already running main loop without exiting and reentering
(or otherwise a way that preserves the old windows)?
At the moment, what each thread does when it is trying to open its
window is:
if self.app.IsMainLoopRunning():
self.app.ExitMainLoop()
x=ReminderWin(self.message)
x.Show()
self.app.MainLoop()
self is the thread, self.app is the app the App, and ReminderWin is a
subclass of Frame which is what I want to be open.
Thanks,
-Taylor

I nominate this for quote of the week. I'm sure we've all felt plenty
of frustration when our coding efforts go awry, but the expression
"will lead only to heartbreak and suffering" made me chuckle, and
smile a crooked grin. Thanks, Tom.

···

On Wed, Jun 24, 2009 at 4:19 PM, Thomas M Wetherbee<tom@wetherbees.com> wrote:

Only do GUI calls from the main thread. Trying to open multiple windows from
multiple threads will lead only to heartbreak and suffering. Put all the
graphic stuff in the main thread, then set up some inter-thread
communication for control.

Tom

--
Best Regards,
Michael Moriarity

Thanks, Michael. That expression comes from years of bitter experience. I started on the PDP-8 with core memory, paper tape, and key switches for manually loading the boot loader. The tools have improved, but the suffering remains the same.

Tom

···

On Wed, 2009-06-24 at 19:22 -0400, Michael Moriarity wrote:

On Wed, Jun 24, 2009 at 4:19 PM, Thomas M Wetherbee<tom@wetherbees.com > > wrote:
> Only do GUI calls from the main thread. Trying to open multiple windows from
> multiple threads will lead only to heartbreak and suffering. Put all the
> graphic stuff in the main thread, then set up some inter-thread
> communication for control.
>
> Tom
I nominate this for quote of the week. I'm sure we've all felt plenty
of frustration when our coding efforts go awry, but the expression
"will lead only to heartbreak and suffering" made me chuckle, and
smile a crooked grin. Thanks, Tom.

I'd say a burning tape is quite a bit more suffering than getting a traceback.

- Josiah

···

On Wed, Jun 24, 2009 at 6:33 PM, Thomas M Wetherbee<tom@wetherbees.com> wrote:

Thanks, Michael. That expression comes from years of bitter experience. I
started on the PDP-8 with core memory, paper tape, and key switches for
manually loading the boot loader. The tools have improved, but the suffering
remains the same. <grin>

Tom

On Wed, 2009-06-24 at 19:22 -0400, Michael Moriarity wrote:

On Wed, Jun 24, 2009 at 4:19 PM, Thomas M Wetherbee<tom@wetherbees.com> > wrote:

Only do GUI calls from the main thread. Trying to open multiple windows
from
multiple threads will lead only to heartbreak and suffering. Put all the
graphic stuff in the main thread, then set up some inter-thread
communication for control.

Tom

I nominate this for quote of the week. I'm sure we've all felt plenty
of frustration when our coding efforts go awry, but the expression
"will lead only to heartbreak and suffering" made me chuckle, and
smile a crooked grin. Thanks, Tom.

>

I had a similar question some days ago. See the discussion below.

http://thread.gmane.org/gmane.comp.python.wxpython/70728

in summary, only one of the threads may instantiate an app object and
run the main loop. This holds for the whole lifetime of the process,
i.e. you cannot stop the thread with the main loop and start a new one
at a later moment.

Regards, Christian

···

On 24 Jun., 19:47, Taylor <tsutton...@gmail.com> wrote:

I'm new to using wxPython (so please bear with me), but I'm having a
little trouble.
I'm writing a program which uses threads, and I want to have each
thread be able to create a window.
From what I understand, there can only be one app and one main loop
and the main loop doesn't return normally until its windows are
closed. So my problem is that if one thread adds a window and calls
MainLoop() so that the window is shown, then another thread in order
to add a window would need to exit and reenter the main loop, but this
kills all the windows that were open. Is there some way to add new
windows to an already running main loop without exiting and reentering
(or otherwise a way that preserves the old windows)?

At the moment, what each thread does when it is trying to open its
window is:

if self.app.IsMainLoopRunning():
self.app.ExitMainLoop()
x=ReminderWin(self.message)
x.Show()
self.app.MainLoop()

self is the thread, self.app is the app the App, and ReminderWin is a
subclass of Frame which is what I want to be open.

I've changed so that all the GUI type things happen in the main
thread, and the other threads' only jobs are to tell the main thread
when to create the new windows. I can't figure out what to do with
MainLoop() though. If I call it after the part that loops to make
windows, no windows work until all are made, which I can't have. If I
put it anywhere else, it will exit before my windows are made.

Here is what I have at the moment:

import datetime, time
import wx
import threading

class Reminder(threading.Thread):
    def __init__(self,message,time):
        threading.Thread.__init__(self)
        self.message=message
        self.time=time
        self.display=False

    def run(self):
        while True:
            if datetime.datetime.now() >= self.time:
                self.display=True
            else:
                time.sleep(1)

if __name__=="__main__":
    app=wx.PySimpleApp()
    x=Reminder("evt1",
               datetime.datetime.now()+datetime.timedelta(0,1))
    y=Reminder("evt2",
               datetime.datetime.now()+datetime.timedelta(0,4))
    x.start()
    y.start()
    lst=[x,y]
    while True:
        for evt in lst[:]:
            if evt.display:
                win=wx.Frame(None,-1,evt.message)
                win.Show()
                lst.remove(evt)
        if lst: time.sleep(1)
        else: break
    app.MainLoop()

···

On Jun 27, 7:50 am, ckkart <ckk...@gmail.com> wrote:

On 24 Jun., 19:47, Taylor <tsutton...@gmail.com> wrote:

I had a similar question some days ago. See the discussion below.

http://thread.gmane.org/gmane.comp.python.wxpython/70728

in summary, only one of the threads may instantiate an app object and
run the main loop. This holds for the whole lifetime of the process,
i.e. you cannot stop the thread with the main loop and start a new one
at a later moment.

Regards, Christian

You do realize that with event driven programming the main loop needs to
run freely to keep everything going, and without it nothing works. You
need to allow the mainloop to start, then process your events in a
handler. Put your GUI methods (subroutines, whatever) in a module not
inside another thread, and invoke them from an event handler with a
callafter.

Tom

···

On Sun, 2009-06-28 at 01:51 -0700, Taylor wrote:

I've changed so that all the GUI type things happen in the main
thread, and the other threads' only jobs are to tell the main thread
when to create the new windows. I can't figure out what to do with
MainLoop() though. If I call it after the part that loops to make
windows, no windows work until all are made, which I can't have. If I
put it anywhere else, it will exit before my windows are made.

Here is what I have at the moment:

import datetime, time
import wx
import threading

class Reminder(threading.Thread):
    def __init__(self,message,time):
        threading.Thread.__init__(self)
        self.message=message
        self.time=time
        self.display=False

    def run(self):
        while True:
            if datetime.datetime.now() >= self.time:
                self.display=True
            else:
                time.sleep(1)

if __name__=="__main__":
    app=wx.PySimpleApp()
    x=Reminder("evt1",
               datetime.datetime.now()+datetime.timedelta(0,1))
    y=Reminder("evt2",
               datetime.datetime.now()+datetime.timedelta(0,4))
    x.start()
    y.start()
    lst=[x,y]
    while True:
        for evt in lst[:]:
            if evt.display:
                win=wx.Frame(None,-1,evt.message)
                win.Show()
                lst.remove(evt)
        if lst: time.sleep(1)
        else: break
    app.MainLoop()

On Jun 27, 7:50 am, ckkart <ckk...@gmail.com> wrote:
> On 24 Jun., 19:47, Taylor <tsutton...@gmail.com> wrote:
>
> I had a similar question some days ago. See the discussion below.
>
> http://thread.gmane.org/gmane.comp.python.wxpython/70728
>
> in summary, only one of the threads may instantiate an app object and
> run the main loop. This holds for the whole lifetime of the process,
> i.e. you cannot stop the thread with the main loop and start a new one
> at a later moment.
>
> Regards, Christian
>