From: James W. <ji...@cs...> - 2008-03-25 21:50:07
|
I'm in Windows XP, and I'm trying to write something like this: while going: do stuff def on_startButton_mouseClick(...): going = 1 def on_stopButton_mouseClick(...): going = 0 My problem is where to put the loop. The best example I could find in the samples was the Gravity program. That program puts the loop in the startButton handler, and Gravity works fine on my machine.]When I do that in my program, it works fine until I push the stop button. Then it freezes up and I have to kill it. I also tried putting the loop in an on_idle(...) method and got the same results. I got around it finally using a timer and it's handler to replace the loop completely, but that's no good to me for two reasons: 2. it's too complicated for beginning students 1. the whole point was to expose them to loops I think the RIGHT way to do this is to use a thread for the loop, but that's also too much for beginning students. Any advice gratefully accepted. -- ------------------------------------------------------------- Jimmy Wilkinson | Professor Emeritus of Computer Science ji...@cs... | The College of Charleston (843) 953-8160 | Charleston SC 29424 http://www.cs.cofc.edu/~jimmy If there is one word to describe me, that word would have to be "profectionist". |
From: Alex T. <al...@tw...> - 2008-03-25 22:40:14
|
James Wilkinson wrote: > I'm in Windows XP, and I'm trying to write something like this: > > > while going: > do stuff > > > def on_startButton_mouseClick(...): > going = 1 > > def on_stopButton_mouseClick(...): > going = 0 > > > That should (might) work, provided you include some important code within the loop (i.e. within "do stuff") - see below. > My problem is where to put the loop. The best example I could find in > the samples was the Gravity program. That program puts the loop in > the startButton handler, and Gravity works fine on my machine.]When I > do that in my program, it works fine until I push the stop button. > Then it freezes up and I have to kill it. I also tried putting the > loop in an on_idle(...) method and got the same results. > > If you have enough info to 'do stuff' right away, you could simply put the loop at the end of your on_initialize() but it's likely that you need to let the user set things up before you are ready to 'do stuff', so you might need a button (e.g. 'Go') and put the loop within its handler. The important thing is that you will be in a tight loop (i.e. everything will freeze) unless you allow a way for the user interaction to happen. The easiest way to do that (see for example the Gravity sample) is to include something like # give the user a chance to click Stop wx.SafeYield(self, True) within the loop. > I got around it finally using a timer and it's handler to replace the > loop completely, but that's no good to me for two reasons: > > More complicated than it needs to be :-) > I think the RIGHT way to do this is to use a thread for the loop, but > that's also too much for beginning students. > > Much too complicated - not just for beginners, but because it's too complicated :-) You only need threads if there is "real work" that could be time consuming needing to happen both in the background and the foreground parts. For simply setting a variable to stop a loop, there is no work, and no need for lengthy processing, in the UI event, so threads are very much overkill. Something along the lines I suggested above, and the Gravity example, should work. If you are having trouble, and if it's not too long or complicated (or secret) include the whole of your code in the next email and we can be more specific. (or simplify 'do stuff' to be something simple like 'print going' and then send the whole code ....) -- Alex Tweedly mailto:al...@tw... www.tweedly.net |
From: Phil E. <ph...@li...> - 2008-03-25 23:27:11
|
Okay, probably not the nicest bit of code I've ever written, but it seems to do the trick: -----begin loop-demo.rsrc.py----- {'application':{'type':'Application', 'name':'Template', 'backgrounds': [ {'type':'Background', 'name':'bgTemplate', 'title':u'Loop Demo', 'size':(380, 220), 'statusBar':1, 'style':['resizeable'], 'menubar': {'type':'MenuBar', 'menus': [ {'type':'Menu', 'name':'menuFile', 'label':'&File', 'items': [ {'type':'MenuItem', 'name':'menuFileExit', 'label':'E&xit', 'command':'exit', }, ] }, ] }, 'components': [ {'type':'StaticText', 'name':'StaticText3', 'position':(10, 45), 'text':u'environment:', }, {'type':'StaticText', 'name':'StaticText2', 'position':(10, 30), 'text':u'known as iteration) in an event-driven programming', }, {'type':'Button', 'name':'stopLoopBtn', 'position':(115, 125), 'label':u'Stop Looping', }, {'type':'Button', 'name':'startLoopBtn', 'position':(10, 125), 'label':u'Start Looping', }, {'type':'Gauge', 'name':'Gauge1', 'position':(15, 80), 'size':(345, 28), 'backgroundColor':(220, 230, 232, 255), 'layout':'horizontal', 'max':10, 'value':0, }, {'type':'StaticText', 'name':'StaticText1', 'position':(10, 15), 'text':u'This program demonstrates a way to control loops (also', }, ] # end components } # end background ] # end backgrounds } } ------end loop-demo.rsrc.py------ -----begin loop-demo.py----- #!/usr/bin/python # simple demonstration of looping # standard Python imports import time # PythonCard imports import wx from PythonCard import model class loopDemo(model.Background): def on_initialize(self, event): self.loopRunning = False self.components.stopLoopBtn.enabled = False print self.components.Gauge1.max print self.components.Gauge1.value def on_startLoopBtn_mouseClick(self, event): if not self.loopRunning: self.components.startLoopBtn.enabled = False self.components.stopLoopBtn.enabled = True self.components.Gauge1.value = 0 self.loopRunning = True self.countValue = 0 while self.countValue < self.components.Gauge1.max: self.countValue += 1 self.components.Gauge1.value = self.countValue wx.Yield() time.sleep(1) print self.countValue def on_stopLoopBtn_mouseClick(self, event): if self.loopRunning: self.loopRunning = False self.countValue = self.components.Gauge1.max + 1 self.components.startLoopBtn.enabled = True self.components.stopLoopBtn.enabled = False self.components.Gauge1.value = 0 if __name__ == '__main__': app = model.Application(loopDemo) app.MainLoop() ------end loop-demo.py------ -- Regards Phil Edwards | PGP/GnuPG Key Id Brighton, UK | 0x68393AEE |
From: Phil E. <ph...@li...> - 2008-03-26 17:31:49
|
Phil Edwards wrote: > Okay, probably not the nicest bit of code I've ever written, but it > seems to do the trick: > Extra brownie points for the first person to spot the bug in the code... :-) -- Regards Phil Edwards | PGP/GnuPG Key Id Brighton, UK | 0x68393AEE |
From: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - 2008-03-26 22:21:15
|
On 26/03/2008 17:31, Phil Edwards wrote: > Phil Edwards wrote: >> Okay, probably not the nicest bit of code I've ever written, but it >> seems to do the trick: >> > > Extra brownie points for the first person to spot the bug in the code... :-) > > Well, my brain's fried after a day of wxPython frames, panels, grids and missing scrollbars. So I had to 'cheat' and run your code because I couldn't see anything. Works OK, apart from the mysterious: self.countValue = self.components.Gauge1.max + 1 which produces a Spinal Tap moment when you hit the stop button...was that intentional ;-) -- XXXXXXXXXXX |
From: Phil E. <ph...@li...> - 2008-04-01 08:56:45
|
Neil Hughes wrote: > > Works OK, apart from the mysterious: > > self.countValue = self.components.Gauge1.max + 1 > > which produces a Spinal Tap moment when you hit the stop button...was > that intentional ;-) > Sort of - that was my quick and dirty way of ensuring that the loop stopped when I wanted it to. The actual bug I meant was that if you run it and let the loop run to completion, it doesn't re-enable the 'Start Loop' button when it's done. Told you it was rubbish code... :-) -- Regards Phil Edwards | PGP/GnuPG Key Id Brighton, UK | 0x68393AEE |