New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Place, Pack and Grid should return the widget #79881
Comments
When you want to simply place a widget on a window and you also want to store the reference for that widget in a variable you can't do that in one line, which is really unpleasant, because when you create a new widget these things are usually the first what you want to do with a widget and breaking it two line is just making things more complicated. For example, if you want to create 3 label, place it next to each other and store their reference: import tkinter as tk
root = tk.Tk()
# you can't do that:
# here the variables assigned to None, since grid() returns 'nothing'
label1 = tk.Label(root).grid(row=0, column=0)
label2 = tk.Label(root).grid(row=0, column=1)
label3 = tk.Label(root).grid(row=0, column=2)
# actually, you must do this:
label1 = tk.Label(root)
label1.grid(row=0, column=0)
label2 = tk.Label(root)
label2.grid(row=0, column=1)
label3 = tk.Label(root)
label3.grid(row=0, column=2) |
Methods place(), pack() and grid() correspond to corresponding Tk commands. These commands return nothing (empty string) in Tk, and Tkinter methods return nothing (None) in Python. If they will became returning something meaningful in future versions of Tk, we will lost a chance to translate this to Python if make them now returning the widget itself. Note also that method chaining is not commonly used in Python. This code would look pretty unpythonic. For these reasons I am against this idea. |
I can somewhat agreed with your point, even if it's not too realistic, but reasonable enough. Also, I'd only use method chaining, because that'd be the only option. I can't pass an argument to tk.Label at creation like 'manager="grid"' or anything like that. In any case, I think doing it in a separate line makes the code longer and less readable even if it's pythonic. Thanks for your consideration. |
I agree with Serhiy that we shouldn't do this; tkinter is (mostly) just a thin wrapper around Tcl/Tk and this isn't enough of a win to deviate from that. In any case, this would be an enhancement that could only go into 3.8 at this point. For your particular example, it would prefer to read the following anyway:
Or if you really want this feature in your own code, try this out:
|
Thank you Zachary, very interesting examples, to say the least! |
Closing as rejected; to my knowledge, *no* built-in Python method both mutate an object and returns the object just mutated, precisely because:
|
Consistency of this rule is a feature. If people got used to writing 'item = Widget(...).geo_manager(...)', they would more often make the mistake of writing buggy code like 'items = lister().sort()'
label1 = tk.Label(root); label1.grid(row=0, column=0)
label2 = tk.Label(root); label2.grid(row=0, column=1)
label3 = tk.Label(root); label3.grid(row=0, column=2) However, in real situations, the widget creation statement is often or usually in the body of a class method and starts with at least an 8 space indent. The call nearly always has a content argument and often other configuration arguments. Such statements often require more than one line even without the manager call added. Manager calls may also have additional arguments. The result is ragged code and if manager calls are appended, they are not so easy to pick out. I believe a majority of experienced tkinter users prefer a style omitted from the opening example: create a batch of widgets; then lay them out. The following untested example shows the idea. It keeps the row and column numbers close together and includes parent grid calls in the layout section. class Viewframe(Frame):
def __init__(self, parent, ...)
...
self.populate()
def populate(self):
label = Label(self, text='hello world', ...)
button = Button(self, text='press me), command=lambda: <do something>)
text = Text(self, ...)
label.grid(row=0, column=0)
button.grid(row=1, column=0)
text.grid(row=0, column=1, rowspan=2, sticky='NSEW')
self.columnconfigure(column=1, weight=1) |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: