Exit Application automatically

Hi,

Given this sample script:

import wx
import time

class CountDialog(wx.Dialog):
    def __init__(self, parent, ID, title, modus):
        wx.Dialog.__init__(self, None, ID, title, style = wx.THICK_FRAME)
        self.label = wx.StaticText(self, -1, "Beginn counting seconds!", style = wx.ALIGN_CENTRE)
        self.seconds = 0
        self.Bind(wx.EVT_TIMER, self.OnTimer)
        self.timer = wx.Timer(self)
        self.timer.Start (1000)

    def OnTimer(self, event):
        self.seconds += 1
        self.label.SetTitle (str(self.seconds) + " seconds")
        if self.seconds == 3:
            print "try exit"
            #wx.GetApp().Exit()
            #wx.PostEvent(self, wx.CloseEvent())
            wx.CallAfter (wx.PostEvent, self, wx.CloseEvent())
            #self.Destroy()

app = wx.App(0)
dialog = CountDialog(None, -1, "", "")
dialog.ShowModal()
dialog.Destroy()
app.MainLoop()

I tried several ways as you see in the commented code,
but nothing works.

Anyone can give me a hint?

Thank you in advance!

···

--
Franz Steinhaeusler

Hi Franz,

see below

Hope this helps
Werner

Franz Steinhaeusler wrote:

Hi,

Given this sample script:

import wx
import time

class CountDialog(wx.Dialog):
   def __init__(self, parent, ID, title, modus):
       wx.Dialog.__init__(self, None, ID, title, style = wx.THICK_FRAME)
       self.label = wx.StaticText(self, -1, "Beginn counting seconds!", style = wx.ALIGN_CENTRE)
       self.seconds = 0
       self.Bind(wx.EVT_TIMER, self.OnTimer)
       self.timer = wx.Timer(self)
       self.timer.Start (1000)

   def OnTimer(self, event):
       self.seconds += 1
       self.label.SetTitle (str(self.seconds) + " seconds")
       if self.seconds == 3:
           print "try exit"

                            self.timer.Stop()
                            self.Close()

···

           #wx.GetApp().Exit()
           #wx.PostEvent(self, wx.CloseEvent())
           wx.CallAfter (wx.PostEvent, self, wx.CloseEvent())
           #self.Destroy()

app = wx.App(0)
dialog = CountDialog(None, -1, "", "")
dialog.ShowModal()
dialog.Destroy()
app.MainLoop()

I tried several ways as you see in the commented code,
but nothing works.

Anyone can give me a hint?

Thank you in advance!

--
Franz Steinhaeusler

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

Hi Werner,

thank you, of course, how easy!
How could I missed that? :slight_smile:

···

On Thu, 27 Apr 2006 15:25:34 +0200, "Werner F. Bruhin" <werner.bruhin@free.fr> wrote:

Hi Franz,

see below

Hope this helps
Werner
[...]

   def OnTimer(self, event):
       self.seconds += 1
       self.label.SetTitle (str(self.seconds) + " seconds")
       if self.seconds == 3:
           print "try exit"

                           self.timer.Stop()
                           self.Close()

           #wx.GetApp().Exit()
           #wx.PostEvent(self, wx.CloseEvent())
           wx.CallAfter (wx.PostEvent, self, wx.CloseEvent())
           #self.Destroy()

--
Franz Steinhaeusler

>Hi Franz,
>
>see below
>
>Hope this helps
>Werner
>[...]
>> def OnTimer(self, event):
>> self.seconds += 1
>> self.label.SetTitle (str(self.seconds) + " seconds")
>> if self.seconds == 3:
>> print "try exit"
>>
>>
> self.timer.Stop()
> self.Close()
>
>> #wx.GetApp().Exit()
>> #wx.PostEvent(self, wx.CloseEvent())
>> wx.CallAfter (wx.PostEvent, self, wx.CloseEvent())
>> #self.Destroy()
>>

Hi Werner,

thank you, of course, how easy!
How could I missed that? :slight_smile:
--

This will only work if this is the only top level frame in the
application (wx automatically exits when there are no more top level
windows unless you tell the wx.App not to). For an unconditional exit,
call wx.App.ExitMainLoop()

···

On 4/27/06, Franz Steinhaeusler <franz.steinhaeusler@gmx.at> wrote:

On Thu, 27 Apr 2006 15:25:34 +0200, "Werner F. Bruhin" <werner.bruhin@free.fr> wrote:

Franz Steinhaeusler

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

>
> >Hi Franz,
> >
> >see below
> >
> >Hope this helps
> >Werner
> >[...]
> >> def OnTimer(self, event):
> >> self.seconds += 1
> >> self.label.SetTitle (str(self.seconds) + " seconds")
> >> if self.seconds == 3:
> >> print "try exit"
> >>
> >>
> > self.timer.Stop()
> > self.Close()
> >
> >> #wx.GetApp().Exit()
> >> #wx.PostEvent(self, wx.CloseEvent())
> >> wx.CallAfter (wx.PostEvent, self, wx.CloseEvent())
> >> #self.Destroy()
> >>
>
>
> Hi Werner,
>
> thank you, of course, how easy!
> How could I missed that? :slight_smile:
> --

This will only work if this is the only top level frame in the
application (wx automatically exits when there are no more top level
windows unless you tell the wx.App not to). For an unconditional exit,
call wx.App.ExitMainLoop()

er, wx.GetApp().ExitMainLoop() that is - you want to call it on your
wx.App object, not on the class.

···

On 4/27/06, Chris Mellon <arkanes@gmail.com> wrote:

On 4/27/06, Franz Steinhaeusler <franz.steinhaeusler@gmx.at> wrote:
> On Thu, 27 Apr 2006 15:25:34 +0200, "Werner F. Bruhin" <werner.bruhin@free.fr> wrote:

> Franz Steinhaeusler
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
> For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org
>
>

The program again:

import wx
import time

class CountDialog(wx.Dialog):
    def __init__(self, parent, ID, title, modus):
        wx.Dialog.__init__(self, None, ID, title, style = wx.THICK_FRAME)
        self.label = wx.StaticText(self, -1, "Beginn counting seconds!", style = wx.ALIGN_CENTRE)
        self.seconds = 0
        self.Bind(wx.EVT_TIMER, self.OnTimer)
        self.timer = wx.Timer(self)
        self.timer.Start (1000)

    def OnTimer(self, event):
        self.seconds += 1
        self.label.SetTitle (str(self.seconds) + " seconds")
        if self.seconds == 3:
            #self.timer.Stop()
            wx.GetApp().ExitMainLoop()
            #self.Close()

app = wx.App(0)
dialog = CountDialog(None, -1, "", "")
dialog.ShowModal()
dialog.Destroy()
app.MainLoop()

But this will not end the program, the dialog counts further,
as nothing happened before.

···

On Thu, 27 Apr 2006 08:58:00 -0500, "Chris Mellon" <arkanes@gmail.com> wrote:

This will only work if this is the only top level frame in the
application (wx automatically exits when there are no more top level
windows unless you tell the wx.App not to). For an unconditional exit,
call wx.App.ExitMainLoop()

er, wx.GetApp().ExitMainLoop() that is - you want to call it on your
wx.App object, not on the class.

--

Franz Steinhaeusler

Hi Franz,

I think what Chris meant is that the self.Close() is not enough, I think you should still stop the timer.

Werner

Franz Steinhaeusler wrote:

···

On Thu, 27 Apr 2006 08:58:00 -0500, "Chris Mellon" <arkanes@gmail.com> wrote:

This will only work if this is the only top level frame in the
application (wx automatically exits when there are no more top level
windows unless you tell the wx.App not to). For an unconditional exit,
call wx.App.ExitMainLoop()

er, wx.GetApp().ExitMainLoop() that is - you want to call it on your
wx.App object, not on the class.

The program again:

import wx
import time

class CountDialog(wx.Dialog):
   def __init__(self, parent, ID, title, modus):
       wx.Dialog.__init__(self, None, ID, title, style = wx.THICK_FRAME)
       self.label = wx.StaticText(self, -1, "Beginn counting seconds!", style = wx.ALIGN_CENTRE)
       self.seconds = 0
       self.Bind(wx.EVT_TIMER, self.OnTimer)
       self.timer = wx.Timer(self)
       self.timer.Start (1000)

   def OnTimer(self, event):
       self.seconds += 1
       self.label.SetTitle (str(self.seconds) + " seconds")
       if self.seconds == 3:
           #self.timer.Stop()
           wx.GetApp().ExitMainLoop()
           #self.Close()

app = wx.App(0)
dialog = CountDialog(None, -1, "", "")
dialog.ShowModal()
dialog.Destroy()
app.MainLoop()

But this will not end the program, the dialog counts further,
as nothing happened before.

Maybe this will work:

import wx
import time

class CountDialog(wx.Dialog):
def init(self, parent, ID, title, modus):
wx.Dialog.init(self, None, ID, title, style = wx.THICK_FRAME)
self.label = wx.StaticText(self, -1, “Beginn counting seconds!”, style = wx.ALIGN_CENTRE)
self.seconds = 0
self.Bind(wx.EVT_TIMER, self.OnTimer)
self.timer = wx.Timer(self)
self.timer.Start (1000)

def OnTimer(self, event):
self.seconds += 1
self.label.SetTitle (str(self.seconds) + " seconds")
if self.seconds == 3:
print “try exit”

       #wx.GetApp().Exit()
       #wx.PostEvent(self, wx.CloseEvent())
       # wx.CallAfter (wx.PostEvent, self, wx.CloseEvent())
       self.EndModal(True)

app = wx.App(0)
dialog = CountDialog(None, -1, “”, “”)

dialog.ShowModal()
dialog.Destroy()
app.MainLoop()

this for example also works:
(also with the use of a button, which I commented out)

Maybe this will work:

import wx
import time

class CountDialog(wx.Dialog):
  def __init__(self, parent, ID, title, modus):
      wx.Dialog.__init__(self, None, ID, title, style = wx.THICK_FRAME)
      self.label = wx.StaticText(self, -1, "Beginn counting seconds!",
style = wx.ALIGN_CENTRE)
      self.seconds = 0
      self.Bind(wx.EVT_TIMER, self.OnTimer)
      self.timer = wx.Timer(self)
      self.timer.Start (1000)

  def OnTimer(self, event):
      self.seconds += 1
      self.label.SetTitle (str(self.seconds) + " seconds")
      if self.seconds == 3:
          print "try exit"
          #wx.GetApp().Exit()
          #wx.PostEvent(self, wx.CloseEvent())
          # wx.CallAfter (wx.PostEvent, self, wx.CloseEvent())

            #b = wx.Button(self)
            #wx.GetTopLevelParent(b).Close()

            wx.GetTopLevelParent(self).Close() #this works also, even if SetTopWindow is not set

···

On Thu, 27 Apr 2006 17:26:06 +0300, "Peter Damoc" <pdamoc@gmail.com> wrote:

          self.EndModal(True)

app = wx.App(0)
dialog = CountDialog(None, -1, "", "")
dialog.ShowModal()
dialog.Destroy()
app.MainLoop()

--

Franz Steinhaeusler

Hi Werner,
yes, this would be more orderly.

The comment was only to try out without stopping the timer.

···

On Thu, 27 Apr 2006 16:24:25 +0200, "Werner F. Bruhin" <werner.bruhin@free.fr> wrote:

Hi Franz,

I think what Chris meant is that the self.Close() is not enough, I think
you should still stop the timer.

Werner

--

Franz Steinhaeusler

Well it might work but way would you wanna do that instead o a simple EndModal?

Because, if this is not the TopLevel Window, it should also work.

Of course the EndModal also would be ok.

What if the Dialog is called non modal?

···

On Thu, 27 Apr 2006 17:42:47 +0300, "Peter Damoc" <pdamoc@gmail.com> wrote:

Well it might work but way would you wanna do that instead o a simple
EndModal?

--

Franz Steinhaeusler

just call
self.Destroy()
in the Timer event followed by
wx.GetApp().ExitMainLoop()

here is the code (I create a frame to simulate the actual Application Frame)

import wx
import time

class CountDialog(wx.Dialog):
def init(self, parent, ID, title, modus):
wx.Dialog.init(self, None, ID, title, style = wx.THICK_FRAME)
self.label = wx.StaticText(self, -1, “Beginn counting seconds!”, style = wx.ALIGN_CENTRE)
self.seconds = 0
self.Bind(wx.EVT_TIMER, self.OnTimer)
self.timer = wx.Timer(self)
self.timer.Start
(1000)

def OnTimer(self, event):
self.seconds += 1
self.label.SetTitle (str(self.seconds) + " seconds")
if self.seconds == 3:
print “try exit”

       self.Destroy()
       wx.GetApp().ExitMainLoop()

app = wx.App(0)
wx.Frame(None).Show()
dialog = CountDialog(None, -1, “”, “”)
dialog.Show()

dialog.Destroy()

app.MainLoop
()

···

On 4/27/06, Franz Steinhaeusler franz.steinhaeusler@gmx.at wrote:

What if the Dialog is called non modal?

>>
>> This will only work if this is the only top level frame in the
>> application (wx automatically exits when there are no more top level
>> windows unless you tell the wx.App not to). For an unconditional exit,
>> call wx.App.ExitMainLoop()
>>
>
>er, wx.GetApp().ExitMainLoop() that is - you want to call it on your
>wx.App object, not on the class.
>

The program again:

import wx
import time

class CountDialog(wx.Dialog):
    def __init__(self, parent, ID, title, modus):
        wx.Dialog.__init__(self, None, ID, title, style = wx.THICK_FRAME)
        self.label = wx.StaticText(self, -1, "Beginn counting seconds!", style = wx.ALIGN_CENTRE)
        self.seconds = 0
        self.Bind(wx.EVT_TIMER, self.OnTimer)
        self.timer = wx.Timer(self)
        self.timer.Start (1000)

    def OnTimer(self, event):
        self.seconds += 1
        self.label.SetTitle (str(self.seconds) + " seconds")
        if self.seconds == 3:
            #self.timer.Stop()
            wx.GetApp().ExitMainLoop()
            #self.Close()

app = wx.App(0)
dialog = CountDialog(None, -1, "", "")
dialog.ShowModal()
dialog.Destroy()
app.MainLoop()

But this will not end the program, the dialog counts further,
as nothing happened before.

Bizarre, and you're right. It's got somethign to do with the modal
event loop - if you replace the ShowModal() call with just Show() it
works fine. Calling EndModal() by itself doesn't fix it, though. I'm
not sure whats going on, really, but ExitMainLoop just plain isn't
working when you've got a modal dialog around (even if EndModal has
been called). I'm pretty sure this has something to do with the
multiple wxEventLoop objects that get created for modal event loops
and it's a problem in the C++ wxWidgets.

Delaying the call to exit by a second (or two) so that the dialog can
call Destroy() and finish killing itself does work. But before
ExitMainLoop() works, you must have called EndModal and the dialog you
called it on must be Destroyed().

This code works (sort of - it's non-determenistic and hackish, but it
points to the problem)

       if self.seconds == 3:
           print "closing"
           wx.FutureCall(1000, wx.GetApp().ExitMainLoop)
           self.EndModal(0)
           self.Destroy()

I wouldn't reccommend this technique in production code, obviously.

···

On 4/27/06, Franz Steinhaeusler <franz.steinhaeusler@gmx.at> wrote:

On Thu, 27 Apr 2006 08:58:00 -0500, "Chris Mellon" <arkanes@gmail.com> wrote:

--

Franz Steinhaeusler

This technique doesn't work for me. The dialog is destroyed, of
course, but the main loop is not exited and the frame stays around.
Does it work for you?

... I'm actually not sure what version of wxPython I'm using right
now, if it's a prebuilt or a version from CVS. I need to modify my
build scripts to add a build date to the wx.VERSION info. Certainly
this is no older than the 2.6.2 release, however.

···

On 4/27/06, Peter Damoc <pdamoc@gmail.com> wrote:

On 4/27/06, Franz Steinhaeusler <franz.steinhaeusler@gmx.at> wrote:

>
> What if the Dialog is called non modal?
>

just call
self.Destroy()
in the Timer event followed by
wx.GetApp().ExitMainLoop()

here is the code (I create a frame to simulate the actual Application Frame)

import wx
import time

class CountDialog(wx.Dialog):
   def __init__(self, parent, ID, title, modus):
       wx.Dialog.__init__(self, None, ID, title, style = wx.THICK_FRAME)
       self.label = wx.StaticText(self, -1, "Beginn counting seconds!",
style = wx.ALIGN_CENTRE)
       self.seconds = 0
       self.Bind(wx.EVT_TIMER, self.OnTimer)
       self.timer = wx.Timer(self)
       self.timer.Start (1000)

   def OnTimer(self, event):
       self.seconds += 1
       self.label.SetTitle (str(self.seconds) + " seconds")
       if self.seconds == 3:
           print "try exit"
            self.Destroy()
           wx.GetApp().ExitMainLoop()

app = wx.App(0)
wx.Frame(None).Show()
dialog = CountDialog(None, -1, "", "")
dialog.Show()
# dialog.Destroy()
app.MainLoop ()

Thank you, yes this also works, even if running without Frame.

···

On Thu, 27 Apr 2006 18:08:14 +0300, "Peter Damoc" <pdamoc@gmail.com> wrote:

On 4/27/06, Franz Steinhaeusler <franz.steinhaeusler@gmx.at> wrote:

What if the Dialog is called non modal?

just call
self.Destroy()
in the Timer event followed by
wx.GetApp().ExitMainLoop()

here is the code (I create a frame to simulate the actual Application Frame)

import wx
import time

class CountDialog(wx.Dialog):
  def __init__(self, parent, ID, title, modus):
      wx.Dialog.__init__(self, None, ID, title, style = wx.THICK_FRAME)
      self.label = wx.StaticText(self, -1, "Beginn counting seconds!",
style = wx.ALIGN_CENTRE)
      self.seconds = 0
      self.Bind(wx.EVT_TIMER, self.OnTimer)
      self.timer = wx.Timer(self)
      self.timer.Start (1000)

  def OnTimer(self, event):
      self.seconds += 1
      self.label.SetTitle (str(self.seconds) + " seconds")
      if self.seconds == 3:
          print "try exit"
          self.Destroy()
          wx.GetApp().ExitMainLoop()

app = wx.App(0)
wx.Frame(None).Show()
dialog = CountDialog(None, -1, "", "")
dialog.Show()
# dialog.Destroy()
app.MainLoop()

--

Franz Steinhaeusler

Everything I posted worked for me

wx (2.6.3.2) on a python 2.4.2

BUT I only tested it on windows… :slight_smile:

Peter

···

On 4/27/06, Chris Mellon arkanes@gmail.com wrote:

This technique doesn’t work for me. The dialog is destroyed, of
course, but the main loop is not exited and the frame stays around.
Does it work for you?

You’re welcome :slight_smile: but if you run without a frame you don’t even need to call the ExitMainLoop because it will end all by itself.

Peter.

···

On 4/27/06, Franz Steinhaeusler franz.steinhaeusler@gmx.at wrote:

Thank you, yes this also works, even if running without Frame.

> This technique doesn't work for me. The dialog is destroyed, of
> course, but the main loop is not exited and the frame stays around.
> Does it work for you?
>

Everything I posted worked for me
wx (2.6.3.2) on a python 2.4.2

BUT I only tested it on windows... :slight_smile:

Ah! Misread your code a bit. You aren't calling ShowModal(), only
Show() on the dialog. If you use ShowModal(), I suspect it will fail
like it does for me.

···

On 4/27/06, Peter Damoc <pdamoc@gmail.com> wrote:

On 4/27/06, Chris Mellon <arkanes@gmail.com> wrote:

Peter

Franz Steinhaeusler wrote:

···

On Thu, 27 Apr 2006 08:58:00 -0500, "Chris Mellon" <arkanes@gmail.com> wrote:

This will only work if this is the only top level frame in the
application (wx automatically exits when there are no more top level
windows unless you tell the wx.App not to). For an unconditional exit,
call wx.App.ExitMainLoop()

er, wx.GetApp().ExitMainLoop() that is - you want to call it on your
wx.App object, not on the class.

The program again:

import wx
import time

class CountDialog(wx.Dialog):
    def __init__(self, parent, ID, title, modus):
        wx.Dialog.__init__(self, None, ID, title, style = wx.THICK_FRAME)
        self.label = wx.StaticText(self, -1, "Beginn counting seconds!", style = wx.ALIGN_CENTRE)
        self.seconds = 0
        self.Bind(wx.EVT_TIMER, self.OnTimer)
        self.timer = wx.Timer(self)
        self.timer.Start (1000)

    def OnTimer(self, event):
        self.seconds += 1
        self.label.SetTitle (str(self.seconds) + " seconds")
        if self.seconds == 3:
            #self.timer.Stop()
            wx.GetApp().ExitMainLoop()
            #self.Close()

app = wx.App(0)
dialog = CountDialog(None, -1, "", "")
dialog.ShowModal()
dialog.Destroy()
app.MainLoop()

But this will not end the program, the dialog counts further,
as nothing happened before.

Control has to be in the MainLoop for ExitMainLoop to have any effect. In this sample it is in ShowModal when ExitMainLoop is called. Causing an exit from ShowModal is what EndModal is for.

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!