I am at the end of a build and am putting some minor touches on and testing; one area I suppose I took for granted (and have honestly not seen a need yet to fully deal with) is the Tkinter buttons. The buttons perform fine overall as to their function; I wish though to completely disable the buttons upon a user selecting them for input. I thought this worked fine as when the button was activated it changed appearance which I took to represent "disabled" and I have not run into the issue in the past knowingly with it.

When the user uses this button, if they do and only then, the button should be completely disabled-- now when I test the button the button darkens (see image below) but it still remains active in the sense that it appears disabled but still allows user input. Strange.

Is "disable" in Tkinter only for appearance? I would think not-- this would make little sense. I do not care what the button looks like, only that it is fully deactivated.

Code used for this button disabling

btn1.config(state = DISABLED)

**Note please disregard the size change of buttons below; this is not an element of the widget-- it has something to do with the image upload to URL image host.

Before User Selection
[IMG]http://i52.photobucket.com/albums/g31/reranger/green.gif[/IMG]


After User Selection\ still works allowing input
[IMG]http://i52.photobucket.com/albums/g31/reranger/disable1.jpg[/IMG]


Thank-you in advance for any help.

Regards,
Matty D

Recommended Answers

All 4 Replies

How is the button connected to the rest of the code? Normally, a DISABLED button will fail to call its 'command=' callback. But if you have, e.g., a .bind('<Button-1>') to catch mouse clicks on the button, I'm willing to bet that those still pass the event. So: code, please?

Jeff

How is the button connected to the rest of the code? Normally, a DISABLED button will fail to call its 'command=' callback. But if you have, e.g., a .bind('<Button-1>') to catch mouse clicks on the button, I'm willing to bet that those still pass the event. So: code, please?

Jeff

Jeff:

Thanks for your reply. Here is an example of the Tkinter button code:

def show_image2():
            canvas2.create_image(100,225, image=photo1)

image01 = PhotoImage(file='green.gif') 
btn1 = Button(root ,bg="Black", image=image01,command=show_image2)  
btn1.configure(state=NORMAL,background='red' )
btn1.pack(side=LEFT,padx=1)

def callback(event):
    if endCard1 == "SA.GIF":
        print "yes"
    else:
        print "no"

    btn3.config(state = DISABLED)
btn1.bind("<Button-1>", callback)

Thanks alot,
Matty

I'm a bit confused about btn3, since I don't see its code. However, I do notice that btn1 does .bind("<Button-1>",callback).

That's actually overkill and can lead to the problem that you describe. If you do this:

btn3 = Button(root, **options, command=callback)

def callback():    # note no event passed!
   do btn3 thing here

then disabling the button should have the desired effect.

Here's a sample piece of code:

from Tkinter import *

class MyFrame(Frame):

    def __init__(self, master):
        Frame.__init__(self, master)
        self.b1 = Button(self, text="Press Me!",command = self.callback)
        self.b2 = Button(self, text="Press Me Too!", command = self.callback2)
        # self.b2.bind('<Button-1>',lambda event:self.callback2())
        self.b1.grid()
        self.b2.grid()

    def callback(self):
        self.b2['state'] = DISABLED

    def callback2(self):
        print "Ha-Ha, you pressed me!"

mainw = Tk()
mainw.f = MyFrame(mainw)
mainw.f.grid()

mainw.mainloop()

As is, the top button disables the bottom one. If you remove the # from line 9, the top button will turn the bottom one grey but the action will still happen BECAUSE the <Button-1> event, even though not registered as an 'activate button' event, is still bound to self.callback2. Thus,
the button is disabled, but it still receives events.

Hope it helps,
Jeff

commented: # very helpful -- mattyd +3

I'm a bit confused about btn3, since I don't see its code. However, I do notice that btn1 does .bind("<Button-1>",callback).

That's actually overkill and can lead to the problem that you describe. If you do this:

btn3 = Button(root, **options, command=callback)

def callback():    # note no event passed!
   do btn3 thing here

then disabling the button should have the desired effect.

Here's a sample piece of code:

from Tkinter import *

class MyFrame(Frame):

    def __init__(self, master):
        Frame.__init__(self, master)
        self.b1 = Button(self, text="Press Me!",command = self.callback)
        self.b2 = Button(self, text="Press Me Too!", command = self.callback2)
        # self.b2.bind('<Button-1>',lambda event:self.callback2())
        self.b1.grid()
        self.b2.grid()

    def callback(self):
        self.b2['state'] = DISABLED

    def callback2(self):
        print "Ha-Ha, you pressed me!"

mainw = Tk()
mainw.f = MyFrame(mainw)
mainw.f.grid()

mainw.mainloop()

As is, the top button disables the bottom one. If you remove the # from line 9, the top button will turn the bottom one grey but the action will still happen BECAUSE the <Button-1> event, even though not registered as an 'activate button' event, is still bound to self.callback2. Thus,
the button is disabled, but it still receives events.

Hope it helps,
Jeff

jrcagle:

Hi, thanks for your reply and help.

This:
btn3.config(state = DISABLED)

Was supposed to be:
btn1.config(state = DISABLED)

(** Another error due to combining cut-and-paste and not paying close enough attention to details.
:rolleyes::lol:)

I am going to closely review your proposed idea concerning my proplem and try to implement it tonight.

Thanks again,
MattyD


Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.