[Tutor] How to shorten this code using classes?

Peter Otten __peter__ at web.de
Wed Nov 23 17:34:07 CET 2011


Mic wrote:

> Hi.
> I have written a simple GUI program. It works just like it is intended to
> do, but there
> is a problem, I feel like I could make it shorter. I thought of using
> classes instead of
> doing it the way I have done.
> 
> Here is my code:
> 
> from tkinter import*
> 
> button1_color="green"
> button1_value=False
> 
> button2_color="green"
> button2_value=False
> 
> 
> class Window(Frame):
>     def __init__(self,master):
>         super (Window,self).__init__(master)
>         self.grid()
>         self.create_widgets()
> 
>     def create_widgets(self):
> 
>         #Creates hello button1
>         self.hello_bttn1=Button(self,bg=button1_color, text="Hi_1",
> command=self.button1_clicked)
>         self.hello_bttn1.grid()
> 
>         #Creates hello button2
>         self.hello_bttn2=Button(self,bg=button2_color, text="Hi_1",
> command=self.button2_clicked)
>         self.hello_bttn2.grid()
> 
> 
> 
>     def button1_clicked(self):
>         """ This method runs if button one is clicked"""
> 
>         def change_button1_value():
>             global button1_value
>             button1_value=not button1_value
> 
>         change_button1_value()
> 
>         if button1_value:
> 
>             self.hello_bttn1.configure(bg="red", text="Hi_2")
> 
>             def change_button1_color_red():
>                 global button1_color
>                 button1_color=("red")
>             change_button1_color_red()
> 
>         else:
>             self.hello_bttn1.configure(bg="green", text="Hi_1")
> 
>             def change_button1_color_green():
>                 global button1_color
>                 button1_color=("green")
>             change_button1_color_green()
> 
>             #-------------------------------------------------
> 
>     def button2_clicked(self):
>         """This method runs if button two is clicked"""
> 
>         def change_button2_value():
>             global button2_value
>             button2_value=not button2_value
> 
>         change_button2_value()
> 
>         if button2_value:
> 
>             self.hello_bttn2.configure(bg="red", text="Hi_2")
> 
>             def change_button2_color_red():
>                 global button2_color
>                 button2_color=("red")
>             change_button2_color_red()
> 
>         else:
>             self.hello_bttn2.configure(text="Hi_1", bg="green")
> 
>             def change_button2_color_green():
>                 global button2_color
>                 button2_color=("green")
>             change_button2_color_green()

> root=Tk()
> root.title("Test")
> root.geometry("200x200")
> app=Window(root)
> root.mainloop()

> As you can button1_clicked and button2_clicked are very similiar. Imagine
> that I would use more buttons than just the two that I am using now.
> 
> It would be a lot of functions then, one for each button. How do I
> accomplish
> the same thing as my code does now, but using one function for all buttons
> instead of one function for each button? Is it possible?

I chose to ignore the "using classes" part. If you like you can turn the 
button_clicked() function into a method of a subclass of Button. You can 
also move the Button configuration done in create_widgets() into the 
__init__() method of that subclass. 

import tkinter as tk
from functools import partial

def button_clicked(button):
    if button["bg"] == "green":
        button.configure(bg="red", text="Hi 2")
    else:
        button.configure(bg="green", text="Hi 1")

class Window(tk.Frame):
    def __init__(self, master):
        super (Window, self).__init__(master)
        self.grid()
        self.create_widgets()

    def create_widgets(self):
        for _ in range(2):
            button = tk.Button(self)
            command = partial(button_clicked, button)
            button["command"] = command
            button.grid()
            command()

root = tk.Tk()
root.title("Test")
root.geometry("200x200")
app = Window(root)
root.mainloop()




More information about the Tutor mailing list