[Tutor] How to shorten this code using classes?
Peter Otten
__peter__ at web.de
Thu Nov 24 12:14:41 CET 2011
Mic wrote:
>>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()
> A very elegant solution. Much better than my previous one. However, I am a
> bit unfamiliar with your way of
> coding, I assume you are used to a version other than Python 3.2?
Yes, though I don't think the difference between 2.x and 3.x matters here.
> Because, never before have I seen either of those
Most tkinter tutorials seem to use
from tkinter import *
which I don't like because it doesn't make explict which names are put into
the current module's namespace. The alternative
import tkinter
leads to long qualified names.
> import tkinter as tk
is a popular compromise.
> from functools import partial
I use this kind of explicit import for a few names that I use frequently,
namely defaultdict, contextmanager, everything from itertools...
I think of these as my personal extended set of builtins ;)
As to the actual partial() function, you probably don't see it a lot because
it has been in the standard library for only three years. The older idiom
for making a function that calls another function with a fixed argument is
command = lambda button=button: button_clicked(button)
> I also wonder, if I implement your solution, is there anyway I can place
> the buttons in the program as I would like, or will they be played in a
> straight, vertical row
> always?
You can iterate over (row, column) pairs instead of the dummy _ variable:
def create_widgets(self):
for row, column in [(0, 0), (1, 1), (2, 2), (3, 0)]:
button = tk.Button(self)
command = partial(button_clicked, button)
button["command"] = command
button.grid(row=row, column=column)
command()
> Also, assume that I have a already have a window with a button in it. If
> you press this button, this window is supposed to open.
> So, if I press the button, will this window open? Because I created the
> previous window using
> from tkinter import* and not import tkinter as tk.
You can make the decision what style you want to use on a per-module basis.
In that module you can then access (for example) a tkinter button with
either tkinter.Button, tk.Button or just Button.
You can even mix styles if you put the respective imports at the beginning
of the module (not recommended).
What approach you take has no consequences on the execution of the program.
> I hope my English is understandable, because it is not my primary
> language. Thanks for your help, it is greatly appreciated!
Many posters aren't native speakers, so you can never be sure that what you
pick up here is actually English ;) I didn't have any problems with your
command of the language, but I'm not a native speaker either.
More information about the Tutor
mailing list