wxPython.button.disabled still catching clicks

Mike Driscoll kyosohma at gmail.com
Tue Dec 30 13:44:33 EST 2008


On Dec 30, 3:04 am, mynthon <mynth... at gmail.com> wrote:
> On Dec 23, 6:12 pm, Mike Driscoll <kyoso... at gmail.com> wrote:
>
>
>
> > On Dec 23, 7:27 am,mynthon<mynth... at gmail.com> wrote:
>
> > > On Dec 23, 11:58 am, Aaron Brady <castiro... at gmail.com> wrote:
>
> > > > On Dec 23, 4:50 am,mynthon<mynth... at gmail.com> wrote:
>
> > > > > Hello! (sorry for my english)
>
> > > > > I have a problem with buttons in wxPython. When button is disabled
> > > > > (by .Disable() or .Enable(False)) it is grayed out but still receive
> > > > > clicks.
>
> > > > > Eg. i have button that disable itself, runs long action and enable
> > > > > itself:
>
> > > > > def onClick(self, evt):
> > > > >     self.btn.Enable(False)
> > > > >     for i in range (1000):
> > > > >         print i
> > > > >     self.btn.Enable(True)
>
> > > > > when for loop is running button is greyed out and when i click on it
> > > > > nothing happens but when loop ends another one is started because
> > > > > button "remebered" thad i click on it when was diabled. My only idea
> > > > > is to reposition button outside frame instead of disabling it but this
> > > > > solution is...not good.
>
> > > > > thanks for any help. Ive searched groups, google and it looks that
> > > > > only i have this problem :)
>
> > > > No, it is very common.  During your for loop, the loop is dominating
> > > > the process completely.  Events are just building up in the app's
> > > > message queue, and don't get handled until after you yield on control.
>
> > > > If you need to run a long task, look into threading, the OnIdle
> > > > method, the 'multiprocessing' module, or pump messages during your
> > > > long task.
>
> > > ok, maybe someone will need it. I dont know how it works because i
> > > didnt have time to read docs and i cannot explain everything. I used
> > > google and wxPython demo (in tree: wxpython overview / process and
> > > events / process)
>
> > > class leftPanel(wx.Panel):
> > >     def __init__(self, parent, id):
> > >         wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
>
> > >         # here you have to define new process, IDLE event, and
> > > onPRocessEnd event
> > >         self.process = None
> > >         self.GetParent().Bind(wx.EVT_IDLE, self.onIdle)
> > >         self.Bind(wx.EVT_END_PROCESS, self.onProcessEnd)
>
> > >         # create button and bind event to it
> > >         self.runScriptBtn = wx.Button(self, -1, 'RUN ME!', (10,220))
> > >         self.runScriptBtn.Bind(wx.EVT_BUTTON, self.onClick,
> > > self.runScriptBtn)
>
> > >     def onClick(self, evt):
> > >         # disable button
> > >         self.runScriptBtn.Enable(False)
>
> > >         # here you have to enter command to run
> > >         # previusly i heve here exec('pythonmyScript.py')
> > >         # but now it will be a subprocess
> > >         cmd = 'pythonxxx1.py'
>
> > >         #create new process
> > >         self.process = wx.Process(self)
>
> > >         # dont know what it is for
> > >         self.process.Redirect()
>
> > >         # execute cmd command
> > >         pid = wx.Execute(cmd, wx.EXEC_ASYNC, self.process)
>
> > >     def onIdle(self, evt):
> > >         # beacuse this method is called only when app enters idle mode
> > >         # the line below is nedded to "simulate" entering idle mode
> > >         # dont know how it works but it works
> > >         evt.RequestMore(True)
>
> > >         # here is some code to catch subprocess output
> > >         if self.process is not None:
> > >             stream = self.process.GetInputStream()
> > >             if stream.CanRead():
> > >                 text = stream.read()
> > >                 print text
>
> > >     def onProcessEnd(self, evt):
> > >         # here is some code to catch subprocess output
> > >         # when it is destroyed
> > >         stream = self.process.GetInputStream()
> > >         if stream.CanRead():
> > >             text = stream.read()
> > >             print text
>
> > >         # dont know it is necessary
> > >         self.process.CloseOutput()
>
> > >         # remove (clear) process object
> > >         self.process.Destroy()
> > >         self.process = None
>
> > >         # show button again
> > >         self.runScriptBtn.Enable()
>
> > I'm pretty sure there's a better way to do this. If you disable the
> > button and click on it, you'll notice that it isn't firing events, so
> > something else is going on here. It seems like the wx.Frame or
> > wx.Application is queuing the mouse button clicks or something. I
> > would post to the wxPython mailing list:http://wxpython.org/maillist.php
>
> > They'll be better able to address this and they'll probably have a
> > simpler solution too.
>
> > Mike
>
> I changed it. Now i'm running separate thread instead of process.
> First example at:http://wiki.wxpython.org/LongRunningTasks

I should have posted that link when I posted originally. Oh well. Glad
you found a workaround.

Mike



More information about the Python-list mailing list