0

I want to create a class for a Tk.Button in a Tk.Frame so that the button can have a border color independent of its background color.

I wrote this code which creates a button in a frame just as I want but I cannot later get or set the text, bcolor and bg of a previously created FrameButton.

I thought I should be able to do this @profile and @bgsetter constructions but these give me an error.

import tkinter as tk

class FramedButton(tk.Frame):
    def __init__(self, parent, text="HELLO", bcolor="red", *args, **kwargs):
        tk.Frame.__init__(self, parent, bg="green", *args, **kwargs)
        self.parent = parent
        self.button=tk.Button(self, text=text, bg=bcolor, borderwidth=1)   
        self.button.grid(row=0, column=0, padx=5, pady=5)
        self.pack()

root = tk.Tk()
root.title="FramedButton"

fb=FramedButton(root)
fb.pack(padx=10,pady=10)

# but these do not work... what do I need to add/change?
fb.text="WORLD"
fb.bg="blue"
fb.bcolor="yellow"

root.mainloop()

2 Answers 2

2

You need to call fb.button.config() to set the options for the internal button and fb.config() to set the options for the outer frame:

fb.config(bg='blue') # set the "outer border" to blue
fb.button.config(text='WORLD', bg='yellow') # the the button text and background color
Sign up to request clarification or add additional context in comments.

Comments

1

The tkinter module is an interface to the Tcl/Tk GUI toolkit. To make actual changes to the widgets, we need to call Tk commands.

Your code doesn't work because you're just creating new data attributes for your instance, not accessing the widget options themselves.

The actual value of a Tk widget option is not related to the attributes of the Python class instance.

The tkinter module defines special methods for getting or setting widget options.

As we can see in the source code, these methods use self.tk.call(args) to call Tk commands to control the Tk GUI.

import tkinter as tk


# inherited from class Misc
print(tk.Frame.configure)
print(tk.Frame.config)
print(tk.Tk.configure)
print(tk.Tk.config)

# inherited from class Wm
# class Wm provides functions for the communication with the window manager.
# for tk.Tk and tk.Toplevel
print(tk.Tk.title)
print(tk.Tk.wm_title)


class FramedButton(tk.Frame):
    def __init__(self, parent, text="HELLO", bcolor="red", *args, **kwargs):
        tk.Frame.__init__(self, parent, bg="green", *args, **kwargs)
        self.parent = parent
        self.button=tk.Button(self, text=text, bg=bcolor, borderwidth=1)   
        self.button.grid(row=0, column=0, padx=5, pady=5)
        self.pack()
        # get button text: self.tk.call(self.button, "cget", "-text")

root = tk.Tk()
# set title
root.title("FramedButton")
# same as root.wm_title("FramedButton") or root.tk.call("wm", "title", root, "FramedButton")

# get title
print(root.title())

fb=FramedButton(root)
fb.pack(padx=10,pady=10)

# available config options
print(root.keys()) # print(root.config())
print(fb.keys()) # print(fb.config())
print(fb.button.keys()) # print(fb.button.config())

# set options
# widget.config(option=value) or widget["option"] = value
fb.button["text"]="WORLD" # set new text to self.button, __setitem__
fb.config(bg="blue") # set new bg to frame
fb.button.config(bg="yellow") # set new bg to self.button

# get button text
print(fb.button["text"]) # __getitem__
print(fb.button.cget("text"))
print(fb.button.config("text"))

root.mainloop()

If you want to customize the attribute lookup, you can use descriptors such as property.

import tkinter as tk


class FramedButton(tk.Frame):
    def __init__(self, parent, text="HELLO", bcolor="red", *args, **kwargs):
        tk.Frame.__init__(self, parent, bg="green", *args, **kwargs)
        self.parent = parent # same as self.master
        self.button=tk.Button(self, text=text, bg=bcolor, borderwidth=1)   
        self.button.grid(row=0, column=0, padx=5, pady=5)
        self.pack()

        self.text = text

    @property
    def text(self):
        return self.button["text"]

    @text.setter
    def text(self, value):
        self.button["text"] = value



root = tk.Tk()
root.title("FramedButton")

fb=FramedButton(root)
fb.pack(padx=10,pady=10)
print(dir(fb))
# [..., 'button', ..., 'parent', ..., 'text', ...]

print(fb.text) # HELLO
fb.text="WORLD"
print(fb.text) # WORLD

print(FramedButton.text)
# <property object at 0x0000012D7E957CE0>

root.mainloop()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.