查找除已使用的锚点之外的另一个锚点位置

3
我已经创建了一个代码来展示我的问题。它看起来像这样:

...

userNameID = tkinter.Label(root, text="Name/ID")
userNameID.place(x=640, y=320, anchor="e")

userNameID = tkinter.Label(root, text="Password")
userNameID.place(x=640, y=360, anchor="e")

entButton = tkinter.Button(root, text="Enter", command=enterPrint)
entButton.place(x=640, y=400, anchor="w")

我遇到了一个问题,我想让文字在中心的一侧对齐,按钮在另一侧。我希望知道文本的左上角锚点位置,以确保所有元素与中心点的距离相同且仍然对齐。


2
如果你现在刚开始学习tkinter,我强烈建议你学习gridpack而不是place。这样会给自己带来很多额外的工作。 - Bryan Oakley
我已经尝试过了,但不幸的是,我发现它们太“不精确”了。在无限网格中,我无法让它有意义。pack函数对我来说似乎没有任何参数,但我可能误解了什么。谢谢你,你在这个网站上的很多答案真的帮助了我。 - SnitchingAuggie
grid()pack()非常精确。你只是还不知道如何实现你想要的。这里和网络上有很多关于你问题的例子。 - Mike - SMT
实际上,我认为网格和包装不是很精确,而这正是关键。您将小部件相对放置,tkinter会为您完成所有数学计算。您不应该关心标签是否以100px结束,输入是否从120开始,您只需要关心标签在左侧,输入在右侧即可。place对于最基本的布局来说肯定更容易学习,但如果您需要UI具有响应性,它很快就会变得非常复杂。 - Bryan Oakley
@BryanOakley 我想我的措辞可能需要改进。grid()pack()设置和更改起来要容易得多和快捷得多。了解如何使用每个功能可以使事情尽可能精确,但我也许不应该说它们更精确。 - Mike - SMT
@Mike-SMT:一旦你学会了,它们就更容易设置和更改,毫无疑问。然而,如果你刚开始接触,可能需要一点学习曲线。虽然两者都非常强大,且使用起来非常简单,但对于某些人来说,理解起来可能有些困难。然而,使用“place”,每个人都可以毫不费力地理解“x=100,y=200”,而无需学习。 - Bryan Oakley
1个回答

5

grid()pack()对大多数需求来说已经足够精准了。你只需要学习如何正确使用这些布局管理器。实际上,几乎从来不需要使用place()。它有其用途,但并不是一般 GUI 设置的最佳选择。也很难管理更新你的代码。

更新:回答您在评论中的问题:

行配置是指将每一行都设置为 1 像素,因为权重吗?我知道我可以在整个程序上绘制一个网格,但我不知道我的程序有多少行、列。因此我找不到中心点。

权重用于告诉特定行或列应该以与其周围其他行和列在同一网格/容器内的比率进行调整大小。默认权重为零。当我们将权重设置为 1 时,该行或列将以相同的速率随窗口一起调整大小。

看看这个示例代码:

import tkinter as tk

root=tk.Tk()

center_frame = tk.Frame(root)
center_frame.grid(row=1, column=1, sticky='nsew')

tk.Label(center_frame, text='Name/ID').grid(row=0, column=0)
tk.Label(center_frame, text='Password').grid(row=1, column=0)
tk.Button(center_frame, text='Enter').grid(row=2, column=1)

root.mainloop()

结果:

enter image description here enter image description here

在上面的示例中,您会发现当您调整窗口大小时,小部件不会移动。这是因为我们没有指示tkinter允许任何行或列移动。
如果我们将此权重添加到程序中root.rowconfigure(0, weight=1)
那么我们就会得到这个效果:

enter image description here

接下来添加这个root.rowconfigure(2, weight=1)

enter image description here

接下来添加这个root.columnconfigure(0, weight=1)

enter image description here

接下来添加这个root.columnconfigure(2, weight=1)

enter image description here

正如您从上面的图片所看到的,根据您设置权重的行和列,行和列将相应地调整大小。我们通过上面的代码实现了将0行和2行以及0列和2列调整大小。而第1行第1列不会调整大小。这意味着我们放置在第1行第1列位置的任何内容都不会调整大小,而是保持相对于边界的位置不变。因为我们在第1行第1列位置设置了一个框架小部件,然后所有的小部件都在框架内,我们有效地将第1行第1列作为中心。
Tkinter有多少行和列取决于您告诉它要有多少。此外,它还会将没有任何内容(小部件)的行和列设置为零大小。这意味着只有具有内容(小部件)的行和列才会影响网格的大小。
假设我们有3行3列。根据我们如何填充它,它将改变所显示内容的大小。
在这个例子中,任何您看到X的地方都表示我们放置了以下行和列的某些内容。
在这个例子中,我们有一些位于(0,0),(1,1)和(2,2)的内容。
                ROW
         0       1       2
     *-------*-------*-------*
     |       |       |       |
   0 |   X   |       |       |
C    |       |       |       |
O    *-------*-------*-------*
L    |       |       |       |
U  1 |       |   X   |       |
M    |       |       |       |
N    *-------*-------*-------*
     |       |       |       |
   2 |       |       |   X   |
     |       |       |       |
     *-------*-------*-------*

在这个例子中,我们有一些位于(0,0)和(2,2)之间的东西。
         0       2
     *-------*-------*
     |       |       |
   0 |   X   |       |
     |       |       |
     *-------*-------*
     |       |       |
   2 |       |   X   |
     |       |       |
     *-------*-------*

在这个例子中,我们有一些位于 (1,0),(2,1) 和 (2,2) 的内容。
         0       1       2
     *-------*-------*-------*
     |       |       |       |
   1 |   X   |       |       |
     |       |       |       |
     *-------*-------*-------*
     |       |       |       |
   2 |       |   X   |   X   |
     |       |       |       |
     *-------*-------*-------*

上述示例说明了根据您使用小部件填充的行和网格自动显示的内容。
至于像sticky这样的参数,它们用于管理每个小部件的行为。例如,如果我们告诉一个小部件填满给定的行/列中的所有空间,那么我们将使用sticky='nsew'。如果我们想要一个小部件在给定的行/列中水平拉伸但不垂直拉伸,我们将使用sticky='ew'表示东/西方向。请记住,sticky参数是用于grid()的。pack()几何管理器有它自己的参数。
有许多选项,您可以在此处找到它们的列表及其描述:
{{link1:对于grid()}}
{{link2:对于pack()}}
看下面的示例。此代码将始终在窗口中心设置标签和按钮,即使您调整窗口大小也是如此。这比place容易得多。

在几何管理器中,有许多有用的参数可用于实现您希望的任何行为或对齐方式。只需花些时间深入了解它。我知道place()看起来像是最好的选择(我在刚开始时也是这么想的,直到Bryan纠正了这个观念:D),但实际上并不是。

import tkinter as tk

root=tk.Tk()
root.rowconfigure(0, weight=1)
root.rowconfigure(2, weight=1)
root.columnconfigure(0, weight=1)
root.columnconfigure(2, weight=1)

center_frame = tk.Frame(root)
center_frame.grid(row=1, column=1, sticky='nsew')

tk.Label(center_frame, text='Name/ID').grid(row=0, column=0)
tk.Label(center_frame, text='Password').grid(row=1, column=0)
tk.Button(center_frame, text='Enter').grid(row=2, column=1)

root.mainloop()

这是一个使用pack()的示例。我发现grid()是我的首选,但pack()也可以实现许多功能。

import tkinter as tk

root=tk.Tk()

center_frame = tk.Frame(root)
center_frame.pack(expand=True)

tk.Label(center_frame, text='Name/ID').pack(side='top')
tk.Label(center_frame, text='Password').pack(side='top')
tk.Button(center_frame, text='Enter').pack(side='right')

root.mainloop()

1
@ReblochonMasque,我能想到的有两个例子:直接将图像添加到按钮上以及在不受GUI调整大小影响的应用程序上设置背景图像。话虽如此,在我编程的一年中,我只有一次需要使用place。 - Mike - SMT
2
@ReblochonMasque:每当您需要放置一个具有绝对位置或相对于另一个小部件的位置,并且不会影响其他小部件或不受其他小部件影响时,就可以使用它。例如,将图像添加为帧或顶层窗口的背景。创建一个小手柄来调整大小。工具提示是另一个潜在的用途。它可用于创建MDI(多文档界面,在另一个窗口内有多个独立移动的窗口)。它没有太多通用用途,但有几个特殊用途。 - Bryan Oakley
1
非常感谢。我现在完全理解一切。 - SnitchingAuggie
“权重”这个词用于告诉tkinter,特定的行或列应该以一定比例随着窗口大小进行调整。但是这种说法略有不准确。权重与行或列相对于窗口的位置无关,而是与同一网格中其他行和列的位置有关。 - Bryan Oakley
@BryanOakley 谢谢。我已经更新了我的措辞,使其更加准确。 - Mike - SMT
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接