New to wxPython: my Simple Counter program doesn't work

Hi!
I'm new to wxPython and I kinda run in circle with this simple counter program.
Why is it that the loop counter doesn't show up?

import sys, os, time
from wxPython.wx import *

class MyFrame(wxFrame):
    def __init__(self, parent, ID, title):
        wxFrame.__init__(self, parent, ID, title,
                         wxDefaultPosition, wxSize(200, 100))

        self.panel = panel = wxPanel(self, -1)

        wxStaticText(panel, -1, "Simple counter",
                     wxDLG_PNT(panel, wxPoint(4, 14)), wxDefaultSize)
        self.counter = wxTextCtrl(panel, -1, "",
                                  wxDLG_PNT(panel, wxPoint(60, 14)),
                                  wxDLG_SZE(panel, wxSize(36, -1)),
                                  wxTE_READONLY)

class MyApp(wxApp):
    def OnInit(self):
        self.frame = MyFrame(NULL, -1, "Simple Counter Demo")
        self.frame.Show(true)
        self.SetTopWindow(self.frame)
        return true

    def Mainloop(self):
        counter = 1
        while counter <= 100:
            self.frame.counter.SetValue("%s" % counter)
            counter += 1
            time.sleep(0.25)

def main():
    app = MyApp(1)
    app.MainLoop()

if __name__ == '__main__':
    main()

Thanx,

Richard Nault

Richard Nault wrote:

Hi!
I'm new to wxPython and I kinda run in circle with this simple counter program.
Why is it that the loop counter doesn't show up?

The first problem seems to be that you misspelled mainloop, so you didn't really override like I assume you think you did. Howeve, even if you fixed that, that's not the way you want to go. Instead, use a timer as shown below.

from wxPython.wx import *

class MyFrame(wxFrame):
    def __init__(self, parent, ID, title):
        wxFrame.__init__(self, parent, ID, title,
                         wxDefaultPosition, wxSize(200, 100))

        self.panel = panel = wxPanel(self, -1)

        wxStaticText(panel, -1, "Simple counter",
                     wxDLG_PNT(panel, wxPoint(4, 14)), wxDefaultSize)
        self.counter = wxTextCtrl(panel, -1, "",
                                  wxDLG_PNT(panel, wxPoint(60, 14)),
                                  wxDLG_SZE(panel, wxSize(36, -1)),
                                  wxTE_READONLY)
        self.timer = wxTimer(self, self.GetId())
        EVT_TIMER(self, self.GetId(), self.OnTimer)
        self.counterval = 1
        self.timer.Start(250)
    def OnTimer(self, event):
        if self.counterval <= 100:
            self.counter.SetValue("%s" % self.counterval)
            self.counterval += 1
        else:
            self.Close()

class MyApp(wxApp):
    def OnInit(self):
        self.frame = MyFrame(NULL, -1, "Simple Counter Demo")
        self.frame.Show(true)
        self.SetTopWindow(self.frame)
        return true

def main():
    app = MyApp(1)
    app.MainLoop()

if __name__ == '__main__':
    main()

Richard Nault wrote:

Hi!
I'm new to wxPython and I kinda run in circle with this simple counter program.
Why is it that the loop counter doesn't show up?

class MyApp(wxApp):
    def OnInit(self):
        self.frame = MyFrame(NULL, -1, "Simple Counter Demo")
        self.frame.Show(true)
        self.SetTopWindow(self.frame)
        return true

    def Mainloop(self):
        counter = 1
        while counter <= 100:
            self.frame.counter.SetValue("%s" % counter)
            counter += 1
            time.sleep(0.25)

Tim Hochberg already provided an alternate structure that'll work for you, but I thought it might be good to mention *why* your attempt won't work.

You're attempting, here, to replace your wxApp's main loop. However, there's a *lot* of stuff that's triggered from the main loop, and your replacement handles none of that. Think of the main loop as an event queue. Events get sent to your application, they're sorted through the queue, and then one at a time are handed off to other chunks of code (event handlers). Many of the events that pass through the queue are things like mouse events, keyboard events, requests from the OS that your application draw itself, etc. Normally, the default mainloop and event handlers that are part of wxApp handle most of this stuff for you. However, you're not using that standard equipment, and as a result all of the events (for example) requesting your application to redraw itself are stacking up, ignored. There's a lot of other background processing that's also getting left undone, too.

Under normal circumstances, with a wxWindows/wxPython program you do *not* want to mess with this main loop. Instead, you want to figure out how your application should respond to particular events (by binding event handlers) and how to get appropriate events sent at the right time. Tim's example deals with the second part by using a wxTimer to send a timer event every quarter second. He then responds to that timer event by incrementing the counter. In between those timer events, there's various other events happening (paint events, mouse events, window resize events, window move events, etc, etc), but you don't need to worry about them because wxWindows handles all of that for you.

Event-driven programming (as in wxPython, and almost all GUI toolkits) requires a bit different mindset than straight procedural programming (as most console apps use). You need to work with this paradigm to get much of anything to work.

Jeff Shannon
Technician/Programmer
Credit International