wxPython.button.disabled still catching clicks

mynthon mynthon1 at gmail.com
Tue Dec 23 08:27:45 EST 2008


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('python myScript.py')
        # but now it will be a subprocess
        cmd = 'python xxx1.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()



More information about the Python-list mailing list