编辑:我已通过 cpython 的 GitHub 问题跟踪器将其作为功能改进提案提交。请参阅问题 100891。
注意:我认识到这个问题可能接近于“基于意见”——如果有更好的讨论场所,请告诉我,我会将其删除。我很欣赏你的坦诚!
对于 tkinter 新手来说,执行以下操作似乎是一个极其常见的陷阱:
my_button = tkinter.Button(text='Hello').pack()
只会遇到错误,因为
my_button
在链接到几何管理器方法后计算为 None
,即 pack
、place
或 grid
。
因此,典型的做法是单独声明小部件并将其添加到几何管理器中,例如:
my_button = tkinter.Button(text='Hello')
my_button.pack()
快速查看几何管理器类的源代码表明,返回调用它们的小部件将是一个极其微不足道的更改。可以将同一行添加到每个几何管理器各自的
_configure
方法中:return self
(我在下面已经这样做了)
class Pack:
"""Geometry manager Pack.
Base class to use the methods pack_* in every widget."""
def pack_configure(self, cnf={}, **kw):
"""Pack a widget in the parent widget. Use as options:
after=widget - pack it after you have packed widget
anchor=NSEW (or subset) - position widget according to
given direction
before=widget - pack it before you will pack widget
expand=bool - expand widget if parent size grows
fill=NONE or X or Y or BOTH - fill widget if widget grows
in=master - use master to contain this widget
in_=master - see 'in' option description
ipadx=amount - add internal padding in x direction
ipady=amount - add internal padding in y direction
padx=amount - add padding in x direction
pady=amount - add padding in y direction
side=TOP or BOTTOM or LEFT or RIGHT - where to add this widget.
"""
self.tk.call(
('pack', 'configure', self._w)
+ self._options(cnf, kw))
return self # return the widget passed to this method
pack = configure = config = pack_configure
class Place:
"""Geometry manager Place.
Base class to use the methods place_* in every widget."""
def place_configure(self, cnf={}, **kw):
"""Place a widget in the parent widget. Use as options:
in=master - master relative to which the widget is placed
in_=master - see 'in' option description
x=amount - locate anchor of this widget at position x of master
y=amount - locate anchor of this widget at position y of master
relx=amount - locate anchor of this widget between 0.0 and 1.0
relative to width of master (1.0 is right edge)
rely=amount - locate anchor of this widget between 0.0 and 1.0
relative to height of master (1.0 is bottom edge)
anchor=NSEW (or subset) - position anchor according to given direction
width=amount - width of this widget in pixel
height=amount - height of this widget in pixel
relwidth=amount - width of this widget between 0.0 and 1.0
relative to width of master (1.0 is the same width
as the master)
relheight=amount - height of this widget between 0.0 and 1.0
relative to height of master (1.0 is the same
height as the master)
bordermode="inside" or "outside" - whether to take border width of
master widget into account
"""
self.tk.call(
('place', 'configure', self._w)
+ self._options(cnf, kw))
return self # return the widget passed to this method
place = configure = config = place_configure
class Grid:
"""Geometry manager Grid.
Base class to use the methods grid_* in every widget."""
# Thanks to Masazumi Yoshikawa ([email protected])
def grid_configure(self, cnf={}, **kw):
"""Position a widget in the parent widget in a grid. Use as options:
column=number - use cell identified with given column (starting with 0)
columnspan=number - this widget will span several columns
in=master - use master to contain this widget
in_=master - see 'in' option description
ipadx=amount - add internal padding in x direction
ipady=amount - add internal padding in y direction
padx=amount - add padding in x direction
pady=amount - add padding in y direction
row=number - use cell identified with given row (starting with 0)
rowspan=number - this widget will span several rows
sticky=NSEW - if cell is larger on which sides will this
widget stick to the cell boundary
"""
self.tk.call(
('grid', 'configure', self._w)
+ self._options(cnf, kw))
return self # return the widget passed to this method
grid = configure = config = grid_configure
我的问题的关键是:任何人都可以解释 tkinter 这个“功能”背后的设计原理吗?最终,这样的更改值得拉取请求/PEP 吗?这会导致 tkinter 发生不当的重大更改吗?
这不一定是一个问题,因为它是在看到这么多关于此行为的问题后进行深入研究的结果。
谁能解释一下 tkinter 这个“功能”背后的设计原理吗?
我猜这是因为 tk 库中的底层方法不返回任何内容。在 tcl/tk 中,不可能在单个语句中创建和管理小部件,因此
pack
、place
和 grid
没有理由返回任何内容。另外,在 tcl/tk 世界中,您可以调用 grid
和 pack
并传入多个小部件,因此返回单个小部件是没有意义的。
恕我直言,这绝对是 tkinter 需要改进的地方。
最终,这样的更改值得拉取请求/PEP 吗?
我个人是这么认为的。
这会导致 tkinter 发生不当的重大更改吗?
我认为这只会导致过度破坏依赖于返回函数的代码
None
。我怀疑有人故意这样做,尽管可能有一些编码不当的程序无意中依赖于这些方法返回的事实None
。
返回新对象的方法通常会被链接起来:
'aBc'.lower().center(10)
变成 ' abc '
。从 .lower()
返回的未命名临时值将被丢弃。在Python中,运算符表达式可以隐式链接对象方法:如果a,b,c属于同一类,则a * b + c
相当于a.__mul__(b).__add__(c)
。或者,根据顺序和优先级,这些方法可能会被嵌套。
Python 避免变异方法链接,因为别名对象可能会导致错误。例如,之后
a = [1, 4, 2, 5, 0]
b = a.sort()
人们会期望 a 和 b 是单独的列表,分别具有原始顺序和排序顺序。在某些语言中,这是事实。这个问题的现实显然是 Guido 在最终确定 Python 之前的经验的一部分。
对于几何方法来说,这似乎不是什么问题。我很想支持这个提议。另一方面, pack 改变了小部件的放置信息,并且 `b = a.pack(...) 要么毫无意义,要么是一个错误。是否有任何/足够的理由使这些方法变得特殊?