[Tutor] Calling Classes From Tkinter Radio Buttons

Peter Otten __peter__ at web.de
Mon Apr 9 10:51:18 CEST 2012


Nathan wrote:

> I'm using Tkinter for a GUI for a program of mine, and I'm trying to
> use radio buttons to select different functions, but it's not working
> right at all. Originally, I had something like
> 
> class ClassOne(self):

You didn't run that code.

>     def ___str___(self):
>         return "This is the base class."
> 
> class ClassTwo(ClassOne):
> 
>     def __str__(self):
>         return "This is the derived class."
> 
> in, say, classes.py, and something like
> 
> import classes
> from Tkinter import *
> 
> class Application(Frame):
> 
>     def __init__(self, master):
>         Frame.__init__(self, master)
>         self.grid()
>         self.widgets()
> 
>     LabelText = classes.ClassOne()
> 
>     def widgets(self):
>         ClassLabel = Label(self, text = self.LabelText)
>         ClassLabel.grid()
> 
> root = Tk()
> app = Application(root)
> root.mainloop()
> 
> in, say, GUI.py. This works perfectly fine, but it only sets the label
> as "This is the base class." What I'd like is a way to use radio
> buttons to configure the text of ClassLabel so that the user can
> choose between the two classes.
> 
> Currently, I'm trying changing GUI.py to something like:

Don't handwave, fix the errors you *can* fix.
 
> import classes
> from Tkinter import *
> 
> class Application(Frame):
> 
>     def __init__(self, master):
>         Frame.__init__(self, master)
>         self.grid()
>         self.widgets()
> 
>     LabelText = classes.ClassOne()
>     classes = ["ClassOne", "ClassTwo"]
> 
>     def widgets(self):
>         self.variable = IntVar()
>         ClassLabel = Label(self, text = self.LabelText)
>         ClassLabel.grid(row = 0)
>         ClassOneButton = Radiobutton(self, text = "This selects the
> base class.", variable = self.variable, value = 0, command =
> self.ChangeClass)
>         ClassOneButton.grid(row = 1, column = 0)
>         ClassTwoButton = Radiobutton(self, text = "This selects the
> derived class.", variable = self.variable, value = 1, command =
> self.ChangeClass)
>         ResetButton = Button(self, text = "Reset the label", command =
> self.ResetLabel)
> 
>     def ResetLabel(self):
>         self.ClassLabel.configure(text = LabelText)
> 
>     def ChangeClass(self):
>         self.selection = self.variable.get()  # This should get the
> value of the selected radio button, right?
>         self.LabelText = self.classes[self.selection]() # LabelText
> changes according to the radio button.
> 
> root = Tk()
> app = Application(root)
> root.mainloop()
> 
> 
> ... but when I run this, BOTH radio buttons are selected, and it still
> just gives me the base class. What am I doing wrong? Is there a way to
> first call a class with a radio button, and then reconfigure the label
> with that class? Any help that can be offered is appreciated!

Keep it simple. If str(ClassOne()) stays the same throughout the lifetime of 
the instance I'd use that string as the associated radio button's value and 
have the label and the radio buttons share the same StringVar.

Below is an example that assumes that the string may change and you want a 
snapshot. Instead of reacting to radio button events all changes of the 
underlying IntVar are traced.

import Tkinter as tk
import datetime

class One(object):
    def time(self):
        return datetime.datetime.now().strftime("%H:%M:%S")
    def __str__(self):
        return self.__class__.__name__ + " at " + self.time()

class Two(One):
    pass

class Application(tk.Frame):

    def __init__(self, master):
        tk.Frame.__init__(self, master)
        self.classes = [One(), Two()]
        self.grid()
        self.widgets()

    def widgets(self):
        self.radiovar = tk.IntVar()
        self.radiovar.trace("w", self.update_label)

        self.labelvar = tk.StringVar()

        label = tk.Label(self, textvariable=self.labelvar)
        label.grid(row=0, column=0)

        for index, text in enumerate([
                "This selects the base class.",
                "This selects the derived class.",]):
            button = tk.Radiobutton(
                self,
                text=text,
                variable=self.radiovar,
                value=index)
            button.grid(row=index+1, column=0, sticky=tk.W)

        self.radiovar.set(0)

    def update_label(self, *args):
        text = self.classes[self.radiovar.get()]
        self.labelvar.set(text)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(root)
    root.mainloop()




More information about the Tutor mailing list