wxPython.button.disabled still catching clicks

M

mynthon

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 :)
 
A

Aaron Brady

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.
 
M

mynthon

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()
 
M

Mike Driscoll

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()

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
 
M

mynthon

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
 
Joined
Mar 12, 2011
Messages
1
Reaction score
0
A quick followup for those (like me) who may run across this when trying to actually block a multiple clicks on a button. A quick-and-dirty method.

In the button click event handler:
button.Enable(False)
--do whatever--
wx.Yield() # handle events which may have been queued up
button.Enable(True)

This doesn't help with the GUI freezing up during a long process of course.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top