Tkinter 网格问题 - 框架未对齐
Tkinter Grid Problem - Frames not aligned
我刚开始使用 tkinter,我仍在努力适应它的工作方式。我试图准备某种包含 4 个部分的网格菜单。
顶部有一个框架,带有应用程序的标题,左侧有一个框架,带有一些用于配置应用程序的按钮,然后是其余 4 个大小相同的框架。
我这里的主要问题是左框和其他四个框之间的空白列,我该如何调整它以便 4 个方块填满 space?
见下方代码:
import datetime
import tkinter as tk
from time import strftime
window = tk.Tk()
window.geometry("1400x800")
window.configure(bg="white")
window.rowconfigure(20,weight=1)
window.columnconfigure(35,weight=1)
window.title("Hello World App")
entry_var_server = tk.StringVar(window,"")
entry_var_db = tk.StringVar(window,"")
entry_var_driver = tk.StringVar(window,"")
def window_widgets():
db_ini_frame_top = tk.Frame(master=window,bg="#57b956",height=120,width=1400,highlightbackground="black",highlightthickness=2)
db_ini_frame_top.grid(rowspan=3,columnspan=34,sticky="w")
db_ini_label_top = tk.Label(master=window,text="Hello World",bg="#57b956")
db_ini_label_top.configure(font=("Calibri",26))
db_ini_label_top.grid(row=1,column=18,sticky="n")
def cur_date(dic = {'01':'st','21':'st','31':'st',
'02':'nd','22':'nd',
'03':'rd','23':'rd'}):
x = strftime('%A, %B %d')
return x + dic.get(x[-2:],'th')+strftime(" %G - %H:%M")
date = cur_date()
db_ini_date = tk.Label(master=window,text=date,bg="#57b956")
db_ini_date.configure(font=("Calibri",12))
db_ini_date.grid(row=0,column=0,sticky="w")
db_ini_frame_left = tk.Frame(master=window,bg="light grey",height=800,width=120,colormap="new",highlightbackground="black",highlightthickness=2)
db_ini_frame_left.grid(row=3,rowspan=16,columnspan=2,sticky="w")
db_ini_frame_center_nw = tk.Frame(master=window,height=350,width=640,bg="blue")
db_ini_frame_center_nw.grid(row=3,column=3,columnspan=16,rowspan=12,sticky="nw")
db_ini_frame_center_sw = tk.Frame(master=window,height=450,width=640,bg="light blue")
db_ini_frame_center_sw.grid(row=12,column=3,columnspan=16,rowspan=12,sticky="sw")
db_ini_frame_center_ne = tk.Frame(master=window,height=350,width=640,bg="light blue")
db_ini_frame_center_ne.grid(row=3,column=19,columnspan=16,rowspan=12,sticky="ne")
db_ini_frame_center_se = tk.Frame(master=window,height=450,width=640,bg="blue")
db_ini_frame_center_se.grid(row=12,column=19,columnspan=16,rowspan=12,sticky="se")
window_widgets()
window.tk.mainloop()
日期字段在单列中,因此它将下一列推向右侧。
更新您的日期块并添加 columnspan=4
date = cur_date()
db_ini_date = tk.Label(master=window,text=date,bg="#57b956")
db_ini_date.configure(font=("Calibri",12))
db_ini_date.grid(row=0,column=0,columnspan=4,sticky="w") # Allow 4 columns for date
输出
虽然我们可以通过一些小的更改来修复您的代码,但花几分钟时间创建一个更智能的布局将使随着应用程序的增长修改您的代码变得更加容易。
我将就如何重组您的代码提供一些建议。答案的最后是一个最终的工作示例。其中 90% 是您的原始代码,但在这里和那里进行了一些调整以使创建 UI 更容易。
不要对所有事情都使用 grid
首先,我建议您不要对所有内容使用grid
。它非常适合创建网格,但有时有更好的方法来布置整个 window。将您的 UI 划分为逻辑分组,然后使用这些分组对它们进行布局。
通过将 UI 组织成多个部分,可以更轻松地只修改一个部分。当您对所有内容使用 grid
时,进行一个小的更改可能需要更改十几行代码,您必须在其中调整行号和列号,以及所有内容的行和列跨度,以适应一个新的小部件。
将布局代码组合在一起
我还建议您将对 grid
和 pack
的调用分组在一起,而不是将它们散布在整个代码中。我发现它使布局可视化变得更容易,并且更容易进行更改,因为所有相关更改彼此靠近而不是分散。
将 UI 分成逻辑部分
您显然拥有三个不同的区域:顶部的标题,左侧的一些按钮,然后是其他所有区域。因此,首先要创建它。当您沿着 space.
的两侧排列东西时,pack
可以说是最佳选择
因此,首先为这三个区域创建框架。然后,您可以使用 pack
根据您的描述沿边缘对齐它们。
db_ini_frame_top = tk.Frame(master=window, ...)
db_ini_frame_left = tk.Frame(master=window, ...)
db_ini_main = tk.Frame(master=window, ...)
db_ini_frame_top.pack(side="top", fill="x")
db_ini_frame_left.pack(side="left", fill="y")
db_ini_main.pack(side="top", fill="both", expand=True)
将其他小部件放入这些容器中
即使您在顶部创建了一个框架,您还是将标签和日期放在了根部 window。您应该将它们放在框架内。当您着手添加按钮时,它们应该位于左侧框架中。最后,对于其他四个windows,他们需要进入第三帧。
db_ini_label_top = tk.Label(master=db_ini_frame_top, ...)
db_ini_date = tk.Label(master=db_ini_frame_top, ...)
db_ini_frame_center_nw = tk.Frame(master=db_ini_main, ...)
db_ini_frame_center_sw = tk.Frame(master=db_ini_main, ...)
db_ini_frame_center_ne = tk.Frame(master=db_ini_main, ...)
db_ini_frame_center_se = tk.Frame(master=db_ini_main, ...)
对实际在一个网格中的四个框架使用grid
当使用 grid
时,一个经验法则是你应该至少给一行和一列一个权重,这样 grid
知道如何处理额外的 space 作为window 增大或缩小。在你的情况下,你希望所有四个单元格都相等,所以你应该给它们相等的权重。
因为您现在只对这四个 windows 使用网格,而不是试图将所有内容都强制到一个网格中,您可以使用有意义的行号和列号(即:第 0 行和第 1 行,列0 和 1,而不是人为地增大行、列和跨度)。
db_ini_frame_center_nw = tk.Frame(master=db_ini_main,height=350,width=640,bg="blue")
db_ini_frame_center_sw = tk.Frame(master=db_ini_main,height=450,width=640,bg="light blue")
db_ini_frame_center_ne = tk.Frame(master=db_ini_main,height=350,width=640,bg="light blue")
db_ini_frame_center_se = tk.Frame(master=db_ini_main,height=450,width=640,bg="blue")
db_ini_main.grid_rowconfigure((0,1), weight=1)
db_ini_main.grid_columnconfigure((0,1), weight=1)
db_ini_frame_center_nw.grid(row=0,column=0, sticky="nsew")
db_ini_frame_center_sw.grid(row=0,column=1, sticky="nsew")
db_ini_frame_center_ne.grid(row=1,column=0, sticky="nsew")
db_ini_frame_center_se.grid(row=1,column=1, sticky="nsew")
这就是您的完整代码的样子。标题区的文字位置我没有调整,但是在不影响GUI.
的其他区域的情况下改变它很容易
此外,请注意,您可以手动调整 window 的大小,一切都会适当地增大或缩小,而不是留下空白点。
import datetime
import tkinter as tk
from time import strftime
window = tk.Tk()
window.geometry("1400x800")
window.configure(bg="white")
window.rowconfigure(20,weight=1)
window.columnconfigure(35,weight=1)
window.title("Hello World App")
entry_var_server = tk.StringVar(window,"")
entry_var_db = tk.StringVar(window,"")
entry_var_driver = tk.StringVar(window,"")
def window_widgets():
db_ini_frame_top = tk.Frame(master=window,bg="#57b956",height=120,width=1400,highlightbackground="black",highlightthickness=2)
db_ini_frame_left = tk.Frame(master=window,bg="light grey",height=800,width=120,colormap="new",highlightbackground="black",highlightthickness=2)
db_ini_main = tk.Frame(master=window,bg="light grey",height=800,width=120,colormap="new",highlightbackground="black",highlightthickness=2)
db_ini_frame_top.pack(side="top", fill="x")
db_ini_frame_left.pack(side="left", fill="y")
db_ini_main.pack(side="top", fill="both", expand=True)
db_ini_label_top = tk.Label(master=db_ini_frame_top,text="Hello World",bg="#57b956")
db_ini_label_top.configure(font=("Calibri",26))
db_ini_label_top.grid(row=1,column=18,sticky="n")
def cur_date(dic = {'01':'st','21':'st','31':'st',
'02':'nd','22':'nd',
'03':'rd','23':'rd'}):
x = strftime('%A, %B %d')
return x + dic.get(x[-2:],'th')+strftime(" %G - %H:%M")
date = cur_date()
db_ini_date = tk.Label(master=db_ini_frame_top,text=date,bg="#57b956")
db_ini_date.configure(font=("Calibri",12))
db_ini_date.grid(row=0,column=0,sticky="w")
db_ini_frame_center_nw = tk.Frame(master=db_ini_main,height=350,width=640,bg="blue")
db_ini_frame_center_sw = tk.Frame(master=db_ini_main,height=450,width=640,bg="light blue")
db_ini_frame_center_ne = tk.Frame(master=db_ini_main,height=350,width=640,bg="light blue")
db_ini_frame_center_se = tk.Frame(master=db_ini_main,height=450,width=640,bg="blue")
db_ini_main.grid_rowconfigure((0,1), weight=1)
db_ini_main.grid_columnconfigure((0,1), weight=1)
db_ini_frame_center_nw.grid(row=0,column=0, sticky="nsew")
db_ini_frame_center_sw.grid(row=0,column=1, sticky="nsew")
db_ini_frame_center_ne.grid(row=1,column=0, sticky="nsew")
db_ini_frame_center_se.grid(row=1,column=1, sticky="nsew")
window_widgets()
window.tk.mainloop()
我刚开始使用 tkinter,我仍在努力适应它的工作方式。我试图准备某种包含 4 个部分的网格菜单。
顶部有一个框架,带有应用程序的标题,左侧有一个框架,带有一些用于配置应用程序的按钮,然后是其余 4 个大小相同的框架。
我这里的主要问题是左框和其他四个框之间的空白列,我该如何调整它以便 4 个方块填满 space?
见下方代码:
import datetime
import tkinter as tk
from time import strftime
window = tk.Tk()
window.geometry("1400x800")
window.configure(bg="white")
window.rowconfigure(20,weight=1)
window.columnconfigure(35,weight=1)
window.title("Hello World App")
entry_var_server = tk.StringVar(window,"")
entry_var_db = tk.StringVar(window,"")
entry_var_driver = tk.StringVar(window,"")
def window_widgets():
db_ini_frame_top = tk.Frame(master=window,bg="#57b956",height=120,width=1400,highlightbackground="black",highlightthickness=2)
db_ini_frame_top.grid(rowspan=3,columnspan=34,sticky="w")
db_ini_label_top = tk.Label(master=window,text="Hello World",bg="#57b956")
db_ini_label_top.configure(font=("Calibri",26))
db_ini_label_top.grid(row=1,column=18,sticky="n")
def cur_date(dic = {'01':'st','21':'st','31':'st',
'02':'nd','22':'nd',
'03':'rd','23':'rd'}):
x = strftime('%A, %B %d')
return x + dic.get(x[-2:],'th')+strftime(" %G - %H:%M")
date = cur_date()
db_ini_date = tk.Label(master=window,text=date,bg="#57b956")
db_ini_date.configure(font=("Calibri",12))
db_ini_date.grid(row=0,column=0,sticky="w")
db_ini_frame_left = tk.Frame(master=window,bg="light grey",height=800,width=120,colormap="new",highlightbackground="black",highlightthickness=2)
db_ini_frame_left.grid(row=3,rowspan=16,columnspan=2,sticky="w")
db_ini_frame_center_nw = tk.Frame(master=window,height=350,width=640,bg="blue")
db_ini_frame_center_nw.grid(row=3,column=3,columnspan=16,rowspan=12,sticky="nw")
db_ini_frame_center_sw = tk.Frame(master=window,height=450,width=640,bg="light blue")
db_ini_frame_center_sw.grid(row=12,column=3,columnspan=16,rowspan=12,sticky="sw")
db_ini_frame_center_ne = tk.Frame(master=window,height=350,width=640,bg="light blue")
db_ini_frame_center_ne.grid(row=3,column=19,columnspan=16,rowspan=12,sticky="ne")
db_ini_frame_center_se = tk.Frame(master=window,height=450,width=640,bg="blue")
db_ini_frame_center_se.grid(row=12,column=19,columnspan=16,rowspan=12,sticky="se")
window_widgets()
window.tk.mainloop()
日期字段在单列中,因此它将下一列推向右侧。
更新您的日期块并添加 columnspan=4
date = cur_date()
db_ini_date = tk.Label(master=window,text=date,bg="#57b956")
db_ini_date.configure(font=("Calibri",12))
db_ini_date.grid(row=0,column=0,columnspan=4,sticky="w") # Allow 4 columns for date
输出
虽然我们可以通过一些小的更改来修复您的代码,但花几分钟时间创建一个更智能的布局将使随着应用程序的增长修改您的代码变得更加容易。
我将就如何重组您的代码提供一些建议。答案的最后是一个最终的工作示例。其中 90% 是您的原始代码,但在这里和那里进行了一些调整以使创建 UI 更容易。
不要对所有事情都使用 grid
首先,我建议您不要对所有内容使用grid
。它非常适合创建网格,但有时有更好的方法来布置整个 window。将您的 UI 划分为逻辑分组,然后使用这些分组对它们进行布局。
通过将 UI 组织成多个部分,可以更轻松地只修改一个部分。当您对所有内容使用 grid
时,进行一个小的更改可能需要更改十几行代码,您必须在其中调整行号和列号,以及所有内容的行和列跨度,以适应一个新的小部件。
将布局代码组合在一起
我还建议您将对 grid
和 pack
的调用分组在一起,而不是将它们散布在整个代码中。我发现它使布局可视化变得更容易,并且更容易进行更改,因为所有相关更改彼此靠近而不是分散。
将 UI 分成逻辑部分
您显然拥有三个不同的区域:顶部的标题,左侧的一些按钮,然后是其他所有区域。因此,首先要创建它。当您沿着 space.
的两侧排列东西时,pack
可以说是最佳选择
因此,首先为这三个区域创建框架。然后,您可以使用 pack
根据您的描述沿边缘对齐它们。
db_ini_frame_top = tk.Frame(master=window, ...)
db_ini_frame_left = tk.Frame(master=window, ...)
db_ini_main = tk.Frame(master=window, ...)
db_ini_frame_top.pack(side="top", fill="x")
db_ini_frame_left.pack(side="left", fill="y")
db_ini_main.pack(side="top", fill="both", expand=True)
将其他小部件放入这些容器中
即使您在顶部创建了一个框架,您还是将标签和日期放在了根部 window。您应该将它们放在框架内。当您着手添加按钮时,它们应该位于左侧框架中。最后,对于其他四个windows,他们需要进入第三帧。
db_ini_label_top = tk.Label(master=db_ini_frame_top, ...)
db_ini_date = tk.Label(master=db_ini_frame_top, ...)
db_ini_frame_center_nw = tk.Frame(master=db_ini_main, ...)
db_ini_frame_center_sw = tk.Frame(master=db_ini_main, ...)
db_ini_frame_center_ne = tk.Frame(master=db_ini_main, ...)
db_ini_frame_center_se = tk.Frame(master=db_ini_main, ...)
对实际在一个网格中的四个框架使用grid
当使用 grid
时,一个经验法则是你应该至少给一行和一列一个权重,这样 grid
知道如何处理额外的 space 作为window 增大或缩小。在你的情况下,你希望所有四个单元格都相等,所以你应该给它们相等的权重。
因为您现在只对这四个 windows 使用网格,而不是试图将所有内容都强制到一个网格中,您可以使用有意义的行号和列号(即:第 0 行和第 1 行,列0 和 1,而不是人为地增大行、列和跨度)。
db_ini_frame_center_nw = tk.Frame(master=db_ini_main,height=350,width=640,bg="blue")
db_ini_frame_center_sw = tk.Frame(master=db_ini_main,height=450,width=640,bg="light blue")
db_ini_frame_center_ne = tk.Frame(master=db_ini_main,height=350,width=640,bg="light blue")
db_ini_frame_center_se = tk.Frame(master=db_ini_main,height=450,width=640,bg="blue")
db_ini_main.grid_rowconfigure((0,1), weight=1)
db_ini_main.grid_columnconfigure((0,1), weight=1)
db_ini_frame_center_nw.grid(row=0,column=0, sticky="nsew")
db_ini_frame_center_sw.grid(row=0,column=1, sticky="nsew")
db_ini_frame_center_ne.grid(row=1,column=0, sticky="nsew")
db_ini_frame_center_se.grid(row=1,column=1, sticky="nsew")
这就是您的完整代码的样子。标题区的文字位置我没有调整,但是在不影响GUI.
的其他区域的情况下改变它很容易此外,请注意,您可以手动调整 window 的大小,一切都会适当地增大或缩小,而不是留下空白点。
import datetime
import tkinter as tk
from time import strftime
window = tk.Tk()
window.geometry("1400x800")
window.configure(bg="white")
window.rowconfigure(20,weight=1)
window.columnconfigure(35,weight=1)
window.title("Hello World App")
entry_var_server = tk.StringVar(window,"")
entry_var_db = tk.StringVar(window,"")
entry_var_driver = tk.StringVar(window,"")
def window_widgets():
db_ini_frame_top = tk.Frame(master=window,bg="#57b956",height=120,width=1400,highlightbackground="black",highlightthickness=2)
db_ini_frame_left = tk.Frame(master=window,bg="light grey",height=800,width=120,colormap="new",highlightbackground="black",highlightthickness=2)
db_ini_main = tk.Frame(master=window,bg="light grey",height=800,width=120,colormap="new",highlightbackground="black",highlightthickness=2)
db_ini_frame_top.pack(side="top", fill="x")
db_ini_frame_left.pack(side="left", fill="y")
db_ini_main.pack(side="top", fill="both", expand=True)
db_ini_label_top = tk.Label(master=db_ini_frame_top,text="Hello World",bg="#57b956")
db_ini_label_top.configure(font=("Calibri",26))
db_ini_label_top.grid(row=1,column=18,sticky="n")
def cur_date(dic = {'01':'st','21':'st','31':'st',
'02':'nd','22':'nd',
'03':'rd','23':'rd'}):
x = strftime('%A, %B %d')
return x + dic.get(x[-2:],'th')+strftime(" %G - %H:%M")
date = cur_date()
db_ini_date = tk.Label(master=db_ini_frame_top,text=date,bg="#57b956")
db_ini_date.configure(font=("Calibri",12))
db_ini_date.grid(row=0,column=0,sticky="w")
db_ini_frame_center_nw = tk.Frame(master=db_ini_main,height=350,width=640,bg="blue")
db_ini_frame_center_sw = tk.Frame(master=db_ini_main,height=450,width=640,bg="light blue")
db_ini_frame_center_ne = tk.Frame(master=db_ini_main,height=350,width=640,bg="light blue")
db_ini_frame_center_se = tk.Frame(master=db_ini_main,height=450,width=640,bg="blue")
db_ini_main.grid_rowconfigure((0,1), weight=1)
db_ini_main.grid_columnconfigure((0,1), weight=1)
db_ini_frame_center_nw.grid(row=0,column=0, sticky="nsew")
db_ini_frame_center_sw.grid(row=0,column=1, sticky="nsew")
db_ini_frame_center_ne.grid(row=1,column=0, sticky="nsew")
db_ini_frame_center_se.grid(row=1,column=1, sticky="nsew")
window_widgets()
window.tk.mainloop()