为什么 tkinter 文本小部件搞砸了我的单元格大小?

Why is the tkinter text widget screwing up my cell sizes?

如下图 1 所示,一切顺利。所有的单元格都是相同的完美尺寸。这很棒。 但接下来是文本框的实现。一切都乱套了。如第二张图片所示,它完全破坏了我的网格布局。我不希望文本框调整单元格大小,我希望它像所有其他小部件一样去我告诉它去的地方。我为此花了几个小时,但无济于事!

import tkinter as tk
from tkinter import ttk, scrolledtext

root = tk.Tk()
root.state('zoomed')
root.configure(background='#8585ad')

for i in range(0,20):
    for x in range(0,20):
        root.columnconfigure(i, weight=1)
        root.rowconfigure(x, weight=1)

for i in range(0, 20): # 0-19(20 is excluded) so this will loop 10x
    for x in range(0, 20):
        tk.Label(root, text=f"C-{i}, R-{x}", bg="green", fg="white").grid(column=i, row=x, sticky="NSEW", padx=1, pady=1)

main_frame = tk.Label(root, text="MAIN FRAME", bg="blue", fg="white", anchor="n").grid(column=1, row=1, columnspan=18, rowspan=18, sticky="NSEW")

frame1 = tk.Label(root, text="FRAME 1", bg="red", fg="white", anchor="n").grid(column=2, row=2, columnspan=3, rowspan=16, sticky="NSEW")
frame2 = tk.Label(root, text="FRAME 2", bg="green", fg="white", anchor="n").grid(column=6, row=2, columnspan=6, rowspan=16, sticky="NSEW")
frame3 = tk.Label(root, text=" FRAME 3", bg="red", fg="white", anchor="n").grid(column=13, row=2, columnspan=5, rowspan=16, sticky="NSEW")

for i in range(2, 5): # start at 2 and end after the 3rd loop.
    for x in range(3, 18): # to loop 15x and for index to start at 3 so i then put (3,18), 18-3 = 15
        tk.Label(root, text=f"Button-{(x-2)}", bg="white", fg="black").grid(column=i, row=x, sticky="EW", padx=5, pady=5)

frame1_header = tk.Label(root, text="User Panel", bg="black", fg="white").grid(column=2, row=2, columnspan=3, sticky="SEW", padx=5, pady=5)
frame2_header = tk.Label(root, text="Editor", bg="black", fg="white").grid(column=6, row=2, columnspan=6, sticky="SEW", padx=5, pady=5)
frame3_header = tk.Label(root, text="Info Panel", bg="black", fg="white").grid(column=13, row=2, columnspan=5, sticky="SEW", padx=5, pady=5)

frame2_text_area = tk.Label(root, text="Text Box", bg="black", fg="white", anchor="center").grid(column=6, row=3, columnspan=4, rowspan=15, sticky="NSEW", padx=5, pady=5)
frame2_list_box = tk.Label(root, text="List Box", bg="grey", fg="white", anchor="center").grid(column=10, row=3, columnspan=2, rowspan=15, sticky="NSEW", padx=5, pady=5)

frame3_tab_panel = ttk.Notebook(root)
frame3_tab_panel.grid(column=13, row=3, columnspan=5, rowspan=15, sticky="NSEW", padx=5, pady=5)
tab1 = ttk.Frame(root)
tab2 = ttk.Frame(root)
tab3 = ttk.Frame(root)
frame3_tab_panel.add(tab1, text ='Generic Editor')
frame3_tab_panel.add(tab2, text ='Text Compare')
frame3_tab_panel.add(tab3, text ='Script Ref')

# width and height does indeed adjust the texbox size but the textbox still isnt properly sticking to the grid that i set.
frame3_tab_panel_tab1 = tk.Text(root, relief="ridge", bd=2, undo=True, wrap="none", background='#1E1E1E', insertbackground='white')#, width=40, height=10)
frame3_tab_panel_tab1.grid(column=13, row=4, columnspan=5, rowspan=14, padx=5, pady=5)
frame3_tab_panel_tab1.config(font=('Consolas bold',10), fg="white")
frame3_tab_panel_tab1.focus()

root.mainloop()

"""
text_area = scrolledtext.ScrolledText(tab1, wrap = tk.WORD, width=40, height=10, font=("Times New Roman", 15))
text_area.grid(column = 0, pady = 10, padx = 10)
text_area.focus()
"""

没有文本框。正如您所见,一切都非常均匀。 仅供参考:这只是我正在处理的一个模板,因此我可以更好地理解 tk 的定位。

文本框没有相应地调整自身并适应我设置的网格,从而破坏了网格。

改变

frame3_tab_panel_tab1.grid(
    column=13, row=4, columnspan=5, rowspan=14, padx=5, pady=5
)

frame3_tab_panel_tab1.grid(
    column=13, row=4, columnspan=5, rowspan=14, padx=5, pady=5,
    sticky="NSEW"
)

我设法通过将 Text() 小部件替换为 scrolledtext.ScrolledText() 小部件来解决它。真奇怪。不需要网格,如果我删除高度和宽度,它就会把它弄乱。为什么高度和宽度会有这样的影响?为什么当你有像列和行这样的配置以及粘性时它甚至存在。 Tkinter 有时对其逻辑非常混乱。不过不管怎样,总算是到了。

这是代码,以防有人遇到类似问题。

import tkinter as tk
from tkinter import ttk, scrolledtext

root = tk.Tk()
root.state('zoomed')
root.configure(background='#8585ad')

for i in range(0,20):
    for x in range(0,20):
        root.columnconfigure(i, weight=1)
        root.rowconfigure(x, weight=1)

for i in range(0, 20): # 0-19(20 is excluded) so this will loop 10x
    for x in range(0, 20):
        tk.Label(root, text=f"C-{i}, R-{x}", bg="green", fg="white").grid(column=i, row=x, sticky="NSEW", padx=1, pady=1)

main_frame = tk.Label(root, text="MAIN FRAME", bg="blue", fg="white", anchor="n").grid(column=1, row=1, columnspan=18, rowspan=18, sticky="NSEW")

frame1 = tk.Label(root, text="FRAME 1", bg="red", fg="white", anchor="n").grid(column=2, row=2, columnspan=3, rowspan=16, sticky="NSEW")
frame2 = tk.Label(root, text="FRAME 2", bg="green", fg="white", anchor="n").grid(column=6, row=2, columnspan=6, rowspan=16, sticky="NSEW")
frame3 = tk.Label(root, text=" FRAME 3", bg="red", fg="white", anchor="n").grid(column=13, row=2, columnspan=5, rowspan=16, sticky="NSEW")

for i in range(2, 5): # start at 2 and end after the 3rd loop.
    for x in range(3, 18): # to loop 15x and for index to start at 3 so i then put (3,18), 18-3 = 15
        tk.Label(root, text=f"Button-{(x-2)}", bg="white", fg="black").grid(column=i, row=x, sticky="EW", padx=5, pady=5)

frame1_header = tk.Label(root, text="User Panel", bg="black", fg="white").grid(column=2, row=2, columnspan=3, sticky="SEW", padx=5, pady=5)
frame2_header = tk.Label(root, text="Editor", bg="black", fg="white").grid(column=6, row=2, columnspan=6, sticky="SEW", padx=5, pady=5)
frame3_header = tk.Label(root, text="Info Panel", bg="black", fg="white").grid(column=13, row=2, columnspan=5, sticky="SEW", padx=5, pady=5)

frame2_text_area = tk.Label(root, text="Text Box", bg="black", fg="white", anchor="center").grid(column=6, row=3, columnspan=4, rowspan=15, sticky="NSEW", padx=5, pady=5)
frame2_list_box = tk.Label(root, text="List Box", bg="grey", fg="white", anchor="center").grid(column=10, row=3, columnspan=2, rowspan=15, sticky="NSEW", padx=5, pady=5)

frame3_tab_panel = ttk.Notebook(root)
frame3_tab_panel.grid(column=13, row=3, columnspan=5, rowspan=15, sticky="NSEW", padx=5, pady=5)

frame3_tab_panel_tab1 = scrolledtext.ScrolledText(root, bd=2, undo=True, wrap="none", width=40, height=10, font=("Times New Roman", 15), background='#1E1E1E', insertbackground='white')
frame3_tab_panel_tab1.config(font=('Consolas bold',10), fg="white")
frame3_tab_panel_tab1.focus()
tab2 = ttk.Frame(root)
tab3 = ttk.Frame(root)
frame3_tab_panel.add(frame3_tab_panel_tab1, text ='Generic Editor')
frame3_tab_panel.add(tab2, text ='Text Compare')
frame3_tab_panel.add(tab3, text ='Script Ref')

root.mainloop()

你的代码中有很多错误,你真的应该接受 a good tutorial for tkinter and you may wish to have a

最大的问题是什么导致您的代码与您预期的不同,您总是将根定义为主。每个小部件,除了 root window 之外,都有一个 master 并且由每个小部件需要的唯一位置参数设置。 请注意,如果给出 None,则默认设置根 window。这是因为 tkinter 是按层次结构构建的,并且在这个层次结构的顶部是 root window(tk.Tk() 的实例)。

master 应该是一个容器,这意味着根 window、Toplevel 或 Frame。大师可以有所谓的 children,它可以是所有其他小部件加上作为 children 处理的框架。 master 和 frame 之间的关系是多种多样的,但是对于这个问题的范围,我们将只看几何。

每个小部件都有一个几何图形,可以被 universal widget method .winfo_geometry() that will give you a geometry string 'widthxheight±x_offset±y_offset'(例如 '120x50-0+20')接收。几何字符串是每个计算的基础,以订购您的小部件,您可以通过选择几何管理器和不同的可选关键字来影响它。使用这些信息将创建一个输出并显示在您的屏幕上。

建议:

import tkinter as tk
from tkinter import ttk, scrolledtext

def populate_frame_1():
    frame_1_label = tk.Label(frame_1,text='User Panel',
                             background = 'black',
                             foreground = 'white')
    frame_1_label.grid(column=0,row=0,sticky='ew',columnspan=3)
    frame_1.columnconfigure(0,weight=1)
    frame_1.columnconfigure(1,weight=1)
    frame_1.columnconfigure(2,weight=1)

    for i in range(0, 3):
        for x in range(1, 16):
            l = tk.Button(frame_1, text=f"Button-{(x-2)}",
                          bg="white", fg="black")
            l.grid(column=i, row=x, sticky="EW", padx=5, pady=5)

def populate_frame_2():
    frame_2_label = tk.Label(frame_2,text='Editor',
                             background = 'black',
                             foreground = 'white')
    textbox = tk.Text(frame_2,width=35)
    listbox = tk.Listbox(frame_2,bg='yellow')
    
    frame_2_label.grid(column=0,row=0,sticky='ew',columnspan=6)
    textbox.grid(column=0,row=1,sticky='ns',columnspan=4)
    listbox.grid(column=4,row=1,sticky='ns',columnspan=2)
    
    frame_2.rowconfigure(1,weight=2)

def populate_frame_3():
    frame_3_label = tk.Label(frame_3,text='Info Panel',
                             background = 'black',
                             foreground = 'white')
    frame_3_label.grid(column=0,row=0,sticky='ew',columnspan=5)

    control_panel = ttk.Notebook(frame_3)
    tab1 = ttk.Frame(control_panel)
    tab2 = ttk.Frame(control_panel)
    tab3 = ttk.Frame(control_panel)
    control_panel.add(tab1, text ='Generic Editor')
    control_panel.add(tab2, text ='Text Compare')
    control_panel.add(tab3, text ='Script Ref')
    control_panel.grid(column=0,row=1,sticky='nswe')

    frame3_tab_panel_tab1 = tk.Text(tab1, relief="ridge", bd=2, undo=True,
                                    wrap="none", background='#1E1E1E',
                                    insertbackground='white',width=40, height=10)
    frame3_tab_panel_tab1.pack(fill=tk.BOTH,expand=True)
    frame3_tab_panel_tab1.config(font=('Consolas bold',10), fg="white")
    frame3_tab_panel_tab1.focus()

    frame_3.rowconfigure(1,weight=2)
    frame_3.columnconfigure(0,weight=2)

XOFFSET = 75
YOFFSET = 50

root = tk.Tk()
root.state('zoomed')
root.configure(background='#8585ad')

main_frame = tk.Frame(root,background='blue')

frame_1 = tk.Frame(main_frame,background='red')
frame_2 = tk.Frame(main_frame,background='green')
frame_3 = tk.Frame(main_frame,background='red')

main_frame.pack(fill=tk.BOTH,expand=True,
                padx=XOFFSET,pady=YOFFSET)
frame_1.pack(side=tk.LEFT,fill=tk.BOTH,padx=XOFFSET,pady=YOFFSET,expand=True)
frame_2.pack(side=tk.LEFT,fill=tk.Y,pady=YOFFSET,expand=True)
frame_3.pack(side=tk.LEFT,fill=tk.BOTH,padx=XOFFSET,pady=YOFFSET,expand=True)

populate_frame_1()
populate_frame_2()
populate_frame_3()

root.mainloop()