You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter Grid布局未将组件放置在正确列位问题

Tkinter Grid布局组件挤在同一列的问题解决

问题描述

尝试使用Tkinter的Grid布局创建可切换双框架的UI,用于用户输入数据。已为各组件设置不同列位,但所有组件均显示在同一列中。

问题代码

import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class GeneralFrame(ttk.Frame):
    def __init__(self, *args):
        super().__init__(*args, padding=10, width=1200, height=600)
        self.grid_propagate(1)

class EntryBox(GeneralFrame):
    def __init__(self, x_location, y_location, *args):
        super().__init__(*args)
        self.entry_box = ttk.Entry(self)
        self.entry_box.place(x=x_location, y=y_location)
        print("Placed")

    def get_data(self):
        return(self.entry_box.get())

class GliderFrame(GeneralFrame):
    def __init__(self, *args):
        super().__init__(*args)

        self.columnconfigure(0, weight=1)
        self.columnconfigure(1, weight=1)
        self.columnconfigure(2, weight=1)

        ttk.Button(self, text="Add Glider", command=self.add_glider).grid(column=0, row=6)

        self.polar_coordinate1_label = ttk.Label(text=str("Minimum Sink X Coordinate:"))
        self.polar_coordinate2_label = ttk.Label(text=str("Minimum Sink Y Coordinate:"))
        self.polar_coordinate3_label = ttk.Label(text=str("Middle Polar X Coordinate:"))
        self.polar_coordinate4_label = ttk.Label(text=str("Middle Polar Y Coordinate:"))
        self.polar_coordinate5_label = ttk.Label(text=str("VNE X Coordinate:"))
        self.polar_coordinate6_label = ttk.Label(text=str("VNE Y Coordinate:"))

        self.polar_coordinate1_entry = ttk.Entry(self)
        self.polar_coordinate2_entry = ttk.Entry(self)
        self.polar_coordinate3_entry = ttk.Entry(self)
        self.polar_coordinate4_entry = ttk.Entry(self)
        self.polar_coordinate5_entry = ttk.Entry(self)
        self.polar_coordinate6_entry = ttk.Entry(self)

    def place_widgets(self):
        self.polar_coordinate1_entry.grid(column=1, row=0, sticky=tk.E)
        self.polar_coordinate2_entry.grid(column=1, row=1, sticky=tk.E)
        self.polar_coordinate3_entry.grid(column=1, row=2, sticky=tk.E)
        self.polar_coordinate4_entry.grid(column=1, row=3, sticky=tk.E)
        self.polar_coordinate5_entry.grid(column=1, row=4, sticky=tk.E)
        self.polar_coordinate6_entry.grid(column=1, row=5, sticky=tk.E)

        self.polar_coordinate1_label.grid(column=0, row=0, sticky=tk.W)
        self.polar_coordinate2_label.grid(column=0, row=1, sticky=tk.W)
        self.polar_coordinate3_label.grid(column=0, row=2, sticky=tk.W)
        self.polar_coordinate4_label.grid(column=0, row=3, sticky=tk.W)
        self.polar_coordinate5_label.grid(column=0, row=4, sticky=tk.W)
        self.polar_coordinate6_label.grid(column=0, row=5, sticky=tk.W)

    def forget_widgets(self):
        self.polar_coordinate1_entry.grid_forget()
        self.polar_coordinate2_entry.grid_forget()
        self.polar_coordinate3_entry.grid_forget()
        self.polar_coordinate4_entry.grid_forget()
        self.polar_coordinate5_entry.grid_forget()
        self.polar_coordinate6_entry.grid_forget()

        self.polar_coordinate1_label.grid_forget()
        self.polar_coordinate2_label.grid_forget()
        self.polar_coordinate3_label.grid_forget()
        self.polar_coordinate4_label.grid_forget()
        self.polar_coordinate5_label.grid_forget()
        self.polar_coordinate6_label.grid_forget()


    def add_glider(self):
        polar_coordinates = [[self.polar_coordinate1_entry.get(), self.polar_coordinate2_entry.get()], [self.polar_coordinate3_entry.get(), self.polar_coordinate4_entry.get()], [self.polar_coordinate5_entry.get(), self.polar_coordinate6_entry.get()]]
        

    def plot_polar(self, polar):
        fig = Figure(figsize = (5, 5), dpi = 100) 
        y = [i**2 for i in range(101)] 
        plot1 = fig.add_subplot(111)
        plot1.plot([0,1,2], [1, 2, 3])

        canvas = FigureCanvasTkAgg(fig, self)   
        canvas.show() 
        canvas.get_tk_widget().grid(side=tk.RIGHT)

class MapFrame(GeneralFrame):
    def __init__(self, *args):
        super().__init__(*args)

        self.turnpoint1_label = ttk.Label(text=str("Turpoint 1:"))
        self.turnpoint2_label = ttk.Label(text=str("Turpoint 2:"))
        self.turnpoint3_label = ttk.Label(text=str("Turpoint 3:"))
        self.turnpoint4_label = ttk.Label(text=str("Turpoint 4:"))
        self.turnpoint5_label = ttk.Label(text=str("Turpoint 5:"))
        self.pilot_mass_label = ttk.Label(text=str("Pilot Weight:"))

        self.turnpoint1_entry = ttk.Entry(self)
        self.turnpoint2_entry = ttk.Entry(self)
        self.turnpoint3_entry = ttk.Entry(self)
        self.turnpoint4_entry = ttk.Entry(self)
        self.turnpoint5_entry = ttk.Entry(self)
        self.pilot_mass_entry = ttk.Entry(self)
        print("Initiated")

    def place_widgets(self):
        self.turnpoint1_entry.grid(column=1, row=0, sticky=tk.E)
        self.turnpoint2_entry.grid(column=1, row=1, sticky=tk.E)
        self.turnpoint3_entry.grid(column=1, row=2, sticky=tk.E)
        self.turnpoint4_entry.grid(column=1, row=3, sticky=tk.E)
        self.turnpoint5_entry.grid(column=1, row=4, sticky=tk.E)
        self.pilot_mass_entry.grid(column=1, row=5, sticky=tk.E)

        self.turnpoint1_label.grid(column=0, row=0, sticky=tk.W)
        self.turnpoint2_label.grid(column=0, row=1, sticky=tk.W)
        self.turnpoint3_label.grid(column=0, row=2, sticky=tk.W)
        self.turnpoint4_label.grid(column=0, row=3, sticky=tk.W)
        self.turnpoint5_label.grid(column=0, row=4, sticky=tk.W)
        self.pilot_mass_label.grid(column=0, row=5, sticky=tk.W)

    def forget_widgets(self):
        self.turnpoint1_entry.grid_forget()
        self.turnpoint2_entry.grid_forget()
        self.turnpoint3_entry.grid_forget()
        self.turnpoint4_entry.grid_forget()
        self.turnpoint5_entry.grid_forget()
        self.pilot_mass_entry.grid_forget()

        self.turnpoint1_label.grid_forget()
        self.turnpoint2_label.grid_forget()
        self.turnpoint3_label.grid_forget()
        self.turnpoint4_label.grid_forget()
        self.turnpoint5_label.grid_forget()
        self.pilot_mass_label.grid_forget()

class MainFrame(GeneralFrame):
    def __init__(self, *args):
        super().__init__(*args)

        self.columnconfigure(0, weight=1)
        self.columnconfigure(1, weight=1)
        self.columnconfigure(2, weight=1)

        ttk.Button(self, text="Switch Frame", command=self.change_frames).grid(column=2, row=0)

        self.MapFrame = MapFrame(self)
        self.GliderFrame = GliderFrame(self)
        self.MapFrame.grid()
        self.MapFrame.place_widgets()
        self.current_frame = 1

    def change_frames(self):
        print("Changing Frames")
        if self.current_frame == 1:     
            self.MapFrame.grid_forget()
            self.MapFrame.forget_widgets()
            self.GliderFrame.grid(column=0, row=0)
            self.GliderFrame.place_widgets()
            self.current_frame = 2
        else:
            self.GliderFrame.grid_forget()
            self.GliderFrame.forget_widgets()
            self.MapFrame.grid(column=0, row=0)
            self.MapFrame.place_widgets()
            self.current_frame = 1

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.geometry("1200x600")
        self.title("Gliding Task Analysis")
        self.main_frame = MainFrame(self)
        self.main_frame.grid(column=0, row=0)

App().mainloop()

问题原因

所有Label组件初始化时未指定父容器(即第一个参数self),导致这些标签默认被添加到根窗口,而非对应的GliderFrame或MapFrame中。根窗口的Grid布局和框架内部的Grid布局是独立的,标签和输入框不在同一容器的布局系统里,最终导致所有组件挤在根窗口的同一列。

解决方法

1. 修正Label的父容器

在创建Label时,必须将当前框架self作为第一个参数传入,确保标签属于框架内部的组件:

# 示例:GliderFrame中的Label修正
self.polar_coordinate1_label = ttk.Label(self, text="Minimum Sink X Coordinate:")

2. 优化框架切换逻辑

框架调用grid_forget()后,其内部所有组件会自动隐藏,不需要额外调用forget_widgets(),可以简化change_frames方法。

3. 调整布局间距(可选)

在grid()方法中添加padx和pady参数,提升界面美观度:

# 示例:输入框的Grid布局添加间距
self.polar_coordinate1_entry.grid(column=1, row=0, sticky=tk.E, padx=5, pady=2)

修改后的完整代码

import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class GeneralFrame(ttk.Frame):
    def __init__(self, *args):
        super().__init__(*args, padding=10, width=1200, height=600)
        self.grid_propagate(1)

class EntryBox(GeneralFrame):
    def __init__(self, x_location, y_location, *args):
        super().__init__(*args)
        self.entry_box = ttk.Entry(self)
        self.entry_box.place(x=x_location, y=y_location)
        print("Placed")

    def get_data(self):
        return self.entry_box.get()

class GliderFrame(GeneralFrame):
    def __init__(self, *args):
        super().__init__(*args)

        self.columnconfigure(0, weight=1)
        self.columnconfigure(1, weight=1)
        self.columnconfigure(2, weight=1)

        ttk.Button(self, text="Add Glider", command=self.add_glider).grid(column=0, row=6, pady=10)

        # 修正:添加self作为父容器
        self.polar_coordinate1_label = ttk.Label(self, text="Minimum Sink X Coordinate:")
        self.polar_coordinate2_label = ttk.Label(self, text="Minimum Sink Y Coordinate:")
        self.polar_coordinate3_label = ttk.Label(self, text="Middle Polar X Coordinate:")
        self.polar_coordinate4_label = ttk.Label(self, text="Middle Polar Y Coordinate:")
        self.polar_coordinate5_label = ttk.Label(self, text="VNE X Coordinate:")
        self.polar_coordinate6_label = ttk.Label(self, text="VNE Y Coordinate:")

        self.polar_coordinate1_entry = ttk.Entry(self)
        self.polar_coordinate2_entry = ttk.Entry(self)
        self.polar_coordinate3_entry = ttk.Entry(self)
        self.polar_coordinate4_entry = ttk.Entry(self)
        self.polar_coordinate5_entry = ttk.Entry(self)
        self.polar_coordinate6_entry = ttk.Entry(self)

        # 直接在__init__中布局,无需单独place_widgets方法
        self._layout_widgets()

    def _layout_widgets(self):
        # 添加padx/pady优化间距
        self.polar_coordinate1_entry.grid(column=1, row=0, sticky=tk.E, padx=5, pady=2)
        self.polar_coordinate2_entry.grid(column=1, row=1, sticky=tk.E, padx=5, pady=2)
        self.polar_coordinate3_entry.grid(column=1, row=2, sticky=tk.E, padx=5, pady=2)
        self.polar_coordinate4_entry.grid(column=1, row=3, sticky=tk.E, padx=5, pady=2)
        self.polar_coordinate5_entry.grid(column=1, row=4, sticky=tk.E, padx=5, pady=2)
        self.polar_coordinate6_entry.grid(column=1, row=5, sticky=tk.E, padx=5, pady=2)

        self.polar_coordinate1_label.grid(column=0, row=0, sticky=tk.W, padx=5, pady=2)
        self.polar_coordinate2_label.grid(column=0, row=1, sticky=tk.W, padx=5, pady=2)
        self.polar_coordinate3_label.grid(column=0, row=2, sticky=tk.W, padx=5, pady=2)
        self.polar_coordinate4_label.grid(column=0, row=3, sticky=tk.W, padx=5, pady=2)
        self.polar_coordinate5_label.grid(column=0, row=4, sticky=tk.W, padx=5, pady=2)
        self.polar_coordinate6_label.grid(column=0, row=5, sticky=tk.W, padx=5, pady=2)

    def add_glider(self):
        polar_coordinates = [
            [self.polar_coordinate1_entry.get(), self.polar_coordinate2_entry.get()],
            [self.polar_coordinate3_entry.get(), self.polar_coordinate4_entry.get()],
            [self.polar_coordinate5_entry.get(), self.polar_coordinate6_entry.get()]
        ]
        print("Polar coordinates saved:", polar_coordinates)

    def plot_polar(self, polar):
        fig = Figure(figsize=(5, 5), dpi=100)
        plot1 = fig.add_subplot(111)
        plot1.plot([0,1,2], [1, 2, 3])

        canvas = FigureCanvasTkAgg(fig, self)
        canvas.draw()
        canvas.get_tk_widget().grid(column=2, row=0, rowspan=6, padx=20)

class MapFrame(GeneralFrame):
    def __init__(self, *args):
        super().__init__(*args)

        # 修正:添加self作为父容器
        self.turnpoint1_label = ttk.Label(self, text="Turnpoint 1:")
        self.turnpoint2_label = ttk.Label(self, text="Turnpoint 2:")
        self.turnpoint3_label = ttk.Label(self, text="Turnpoint 3:")
        self.turnpoint4_label = ttk.Label(self, text="Turnpoint 4:")
        self.turnpoint5_label = ttk.Label(self, text="Turnpoint 5:")
        self.pilot_mass_label = ttk.Label(self, text="Pilot Weight:")

        self.turnpoint1_entry = ttk.Entry(self)
        self.turnpoint2_entry = ttk.Entry(self)
        self.turnpoint3_entry = ttk.Entry(self)
        self.turnpoint4_entry = ttk.Entry(self)
        self.turnpoint5_entry = ttk.Entry(self)
        self.pilot_mass_entry = ttk.Entry(self)

        # 直接在__init__中布局
        self._layout_widgets()

    def _layout_widgets(self):
        self.turnpoint1_entry.grid(column=1, row=0, sticky=tk.E, padx=5, pady=2)
        self.turnpoint2_entry.grid(column=1, row=1, sticky=tk.E, padx=5, pady=2)
        self.turnpoint3_entry.grid(column=1, row=2, sticky=tk.E, padx=5, pady=2)
        self.turnpoint4_entry.grid(column=
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 08:02:39