PythonCard - My app stuck when button clicked
daved170 at gmail.com
Thu May 14 11:08:51 EDT 2009
On May 14, 2:37 pm, Dave Angel <da... at ieee.org> wrote:
> daved170 wrote:
> > On May 13, 7:42 pm, Dave Angel <da... at ieee.org> wrote:
> >> daved170 wrote:
> >>> Hi there,
> >>> I'm newbie in pythonCard.
> >>> I have an application with 2 buttons : START , STOP
> >>> Start execute a while(1) loop that execute my calculations.
> >>> Stop suppose to raise a flag that will end that loop.
> >>> Whenever I pish the START button my GUI is stuck. the calculation
> >>> executes but I can't push the STOP button.
> >>> I added thread that START start a thread that execute my calculations.
> >>> I also added a Global variable that will hold the indication if the
> >>> loop should continue.
> >>> The problem now is that the thread ignore that variable and loop
> >>> forever.
> >>> Is there a simple way to make sure that the GUI won't stuck (without
> >>> threads)?
> >>> And if there isn't such way I would appriciet it very much if anyone
> >>> could post an example of how to make my thread read that variable
> >>> Thanks
> >>> Dave
> >> I don't know PythonCard, but most GUI's are similar enough that the
> >> concepts will work, even though the details differ. I'll assume that
> >> PythonCard has a traditional event loop, from which all events are
> >> dispatched.
> >> If your loop is fairly small, then you should keep it to one thread.
> >> Debugging it will usually be much easier. The trick is to break the
> >> task into pieces (each piece might be once around what is now a loop),
> >> and invoke one piece each time the event loop empties. I can't tell you
> >> how to do that without seeing your loop, but it's not usually very hard.
> >> Now, there is some way of POSTing an event to the event loop. That puts
> >> the event *after* all the events that are already there, but returns
> >> control immediately. So create a custom event, and POST it from the
> >> START button's button-pressed event. That will fire off one "loop" of
> >> the special task, in other words, make one function call to your new
> >> function. Then at the end of the function, POST it again, unless the
> >> STOP button has been pressed in the meantime.
> >> An optimization for this is to use coroutines, which are usually done
> >> with a generator. It's much trickier to describe, but much easier to
> >> accomplish. Roughly, you'd take your existing loop, and put a yield
> >> statement in it at appropriate place(s). Then the custom event is
> >> simply a call to the .next() function of that generator.
> >> Now, threading isn't that tough either, depending on how much data is
> >> being shared between the thread and the main program. You say that
> >> sharing a global flag isn't working, but it should. So how about if you
> >> show us some code, and somebody'll spot the trouble. For example, is
> >> the thread defined in the same module as the App? Global only shares
> >> between a single module. Another reason globals might seem to fail is
> >> if you tried to do mutual imports between two or more modules. (A
> >> imports B, which imports A). Sometimes that fails in mysterious ways.
> >> Make a simple (stripped) example of what you're trying, and we'll try to
> >> find the problem. Without concrete code, we end up with ambiguities
> >> like the above usage of two different meanings for "the loop."- Hide quoted text -
> >> - Show quoted text -
> > Thank's Dave,
> > Here my code, It's a very simple app. the Start button starts a TCP/IP
> > communication and the Stop should dtop it and kill the client.
> > I'll be thankful if you'll be able to spot my mistake.
> > Thanks again
> > Dave
> > #Global Variable
> > bStopLoop =alse
> > #Global Function
> > def execute(sockObj):
> > while(!bStopLoop):
> > str =ockObj.recv(1024)
> > tmpStr =Hello " + str
> > sockObj.send(tmpStr)
> > #Thread handle class
> > class myThread(threading.Thread):
> > def __init__(self,sockObj):
> > threading.Thread.__init__(self)
> > bStopLoop =alse
> > self.sockObj =ockObj
> > def run(self):
> > execute(self.SockObj)
> > # GUI
> > class GUI(model.Background)
> > def on_Start_mouseclick(self,event):
> > try:
> > event.target.enable =alse
> > event.target.redraw()
> > self.components.Start.enable =alse
> > self.currThread =yThread(self.sockObj)
> > self.currThread.Start()
> > wx.SafeYield(self)
> > self.components.Start.enable =rue
> > except:
> > .....
> > def on_Stop_mouseclick(self,event):
> > bStopLoop =rue
> In the two methods that try to change bStopLoop, you don't declare it
> global. Add the line "global bStopLoop" to beginning of both
> on_Start_mouseclick() and on_Stop_mouseclick(), and (my preference) to function execute()
> The semantics of global versus local variables for non-nested functions/methods is roughly: if a function or method assigns to a name, it's taken to be a local, unless it's explicitly declared as global.- Hide quoted text -
> - Show quoted text -
Thanks Dave. It works! It solved that problem. Now all i need is to
stop the socket in a way that whenever I push the Start button again
my app won't raise network connectio, but I think I'll handle that by
More information about the Python-list