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

调整Tkinter TopLevel窗口中控件垂直间距并添加新组件

问题描述

使用Python Tkinter开发自动化数据预处理工具时,在TopLevel窗口new_window中需要实现以下布局调整:

  • 缩小text_widget3与inputs_frame之间的垂直空白间距
  • 将inputs_frame置于text_widget3正下方
  • 在inputs_frame下方添加text_widget4

当前窗口代码及完整程序代码如下:

当前open_new_window方法代码

def open_new_window(self):
    new_window = tk.Toplevel()
    new_window.title("New Window")
    
    # 设置窗口全屏
    new_window.state('zoomed')

    # 创建左侧第一个文本组件
    text_widget = tk.Text(new_window, bd=2, relief=tk.GROOVE, width=70, height=20)
    text_widget.grid(row=0, column=0, padx=15, pady=10, sticky="nw")

    # 输出df.info()到文本组件
    with io.StringIO() as stream:
        self.df.info(buf=stream)
        output = stream.getvalue()
        text_widget.insert(tk.END, output)
        
    # 设置文本组件不可编辑
    text_widget.config(state="disabled")
            
    # 创建左侧第二个文本组件
    text_widget2 = tk.Text(new_window, bd=2, relief=tk.GROOVE, width=70, height=22)
    text_widget2.grid(row=1, column=0, padx=15, pady=5, sticky="sw")
         
    # 创建右侧第一个文本组件
    text_widget3 = tk.Text(new_window, bd=2, relief=tk.GROOVE, width=80, height=3)
    text_widget3.grid(row=0, column=1, padx=15, pady=10, rowspan=1, sticky="ne")
    
    # 创建输入框框架
    inputs_frame = tk.Frame(new_window, bd=2, relief=tk.GROOVE, width=text_widget3["width"])
    inputs_frame.grid(row=1, column=1, padx=15, pady=10, sticky="new")

    # 输入框内容
    label1 = tk.Label(inputs_frame, text="Label 1:")
    label1.grid(row=0, column=0, padx=5, pady=5, sticky="w")
    input1 = tk.Entry(inputs_frame)
    input1.grid(row=0, column=1, padx=5, pady=5, sticky="w")

    label2 = tk.Label(inputs_frame, text="Label 2:")
    label2.grid(row=1, column=0, padx=5, pady=5, sticky="w")
    input2 = tk.Entry(inputs_frame)
    input2.grid(row=1, column=1, padx=5, pady=5, sticky="w")

    # 添加按钮
    add_button = tk.Button(inputs_frame, text="Add", width=10)
    add_button.grid(row=2, column=0, columnspan=2, pady=10)

完整程序代码

import tkinter as tk, pandas as pd, io
from tkinter import ttk, filedialog

class DataWizard:
    def __init__(self, root):
        self.root = root
        self.root.title("Data Wizard: Automated Data Preprocessing")
        self.root.geometry("800x600")

        # 顶部标题布局
        self.title_label = tk.Label(self.root, text="Data Wizard: Automated Data Preprocessing", font=("Arial", 18))
        self.title_label.pack(pady=20)

        # 中间表格框架
        self.table_frame = tk.Frame(self.root, bd=2, relief=tk.GROOVE)
        self.table_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)

        # 创建表格树视图
        self.tree = ttk.Treeview(self.table_frame, selectmode='browse')
        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        # 添加垂直滚动条
        scrollbar = ttk.Scrollbar(self.table_frame, orient="vertical", command=self.tree.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.tree.configure(yscrollcommand=scrollbar.set)

        # 底部上传布局
        self.bottom_frame = tk.Frame(self.root, bd=2, relief=tk.GROOVE)
        self.bottom_frame.pack(fill=tk.X, padx=20, pady=10)

        self.upload_label = tk.Label(self.bottom_frame, text="Upload CSV file", font=("Arial", 12))
        self.upload_label.pack(side=tk.LEFT, padx=10, pady=10)

        self.upload_button = tk.Button(self.bottom_frame, text="Browse", command=self.upload_csv)
        self.upload_button.pack(side=tk.RIGHT, padx=10, pady=10)

        # 新窗口按钮框架
        self.new_frame = tk.Frame(self.root, bd=0, relief=tk.GROOVE)
        self.new_frame.pack(fill=tk.X, padx=20, pady=10)
        
        self.new_window_button = tk.Button(self.new_frame, text="Next", command=self.open_new_window)
        self.new_window_button.pack(side=tk.RIGHT, padx=10, pady=10)

    def upload_csv(self):
        # 选择CSV文件
        file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])

        if file_path:
            # 读取CSV为DataFrame
            self.df = pd.read_csv(file_path)

            # 设置树视图列
            self.tree["columns"] = list(self.df.columns)

            # 设置列标题和宽度
            for col in self.df.columns:
                self.tree.heading(col, text=col.title())
                self.tree.column(col, width=len(str(self.df[col].max())), anchor = tk.CENTER)

            # 插入数据
            for i, row in self.df.iterrows():
                self.tree.insert("", "end", values=list(row))

            # 更新上传标签为文件名
            self.upload_label.config(text=file_path)

            # 添加水平滚动条
            horizontal_scrollbar = ttk.Scrollbar(self.table_frame, orient="horizontal", command=self.tree.xview)
            horizontal_scrollbar.pack(side=tk.BOTTOM, fill=tk.X)
            self.tree.configure(xscrollcommand=horizontal_scrollbar.set)

    def open_new_window(self):
        new_window = tk.Toplevel()
        new_window.title("New Window")
        
        # 设置窗口全屏
        new_window.state('zoomed')

        # 创建左侧第一个文本组件
        text_widget = tk.Text(new_window, bd=2, relief=tk.GROOVE, width=70, height=20)
        text_widget.grid(row=0, column=0, padx=15, pady=10, sticky="nw")

        # 输出df.info()到文本组件
        with io.StringIO() as stream:
            self.df.info(buf=stream)
            output = stream.getvalue()
            text_widget.insert(tk.END, output)
            
        # 设置文本组件不可编辑
        text_widget.config(state="disabled")
                
        # 创建左侧第二个文本组件
        text_widget2 = tk.Text(new_window, bd=2, relief=tk.GROOVE, width=70, height=22)
        text_widget2.grid(row=1, column=0, padx=15, pady=5, sticky="sw")
             
        # 创建右侧第一个文本组件
        text_widget3 = tk.Text(new_window, bd=2, relief=tk.GROOVE, width=80, height=3)
        text_widget3.grid(row=0, column=1, padx=15, pady=10, rowspan=1, sticky="ne")
        
        # 创建输入框框架
        inputs_frame = tk.Frame(new_window, bd=2, relief=tk.GROOVE, width=text_widget3["width"])
        inputs_frame.grid(row=1, column=1, padx=15, pady=10, sticky="new")

        # 输入框内容
        label1 = tk.Label(inputs_frame, text="Label 1:")
        label1.grid(row=0, column=0, padx=5, pady=5, sticky="w")
        input1 = tk.Entry(inputs_frame)
        input1.grid(row=0, column=1, padx=5, pady=5, sticky="w")

        label2 = tk.Label(inputs_frame, text="Label 2:")
        label2.grid(row=1, column=0, padx=5, pady=5, sticky="w")
        input2 = tk.Entry(inputs_frame)
        input2.grid(row=1, column=1, padx=5, pady=5, sticky="w")

        # 添加按钮
        add_button = tk.Button(inputs_frame, text="Add", width=10)
        add_button.grid(row=2, column=0, columnspan=2, pady=10)
        
              
                
if __name__ == "__main__":
    root = tk.Tk()
    app = DataWizard(root)
    root.mainloop()
解决方案

问题根源是右侧组件直接放在new_window的grid布局中,受左侧text_widget的行高影响,导致text_widget3和inputs_frame之间被拉长。解决方法是给右侧组件单独创建容器frame,让它们在内部独立布局,不受左侧行高干扰。

修改后的open_new_window方法代码如下:

def open_new_window(self):
    new_window = tk.Toplevel()
    new_window.title("New Window")
    
    # 设置窗口全屏
    new_window.state('zoomed')

    # 左侧第一个文本组件
    text_widget = tk.Text(new_window, bd=2, relief=tk.GROOVE, width=70, height=20)
    text_widget.grid(row=0, column=0, padx=15, pady=10, sticky="nw")

    # 输出df.info()内容
    with io.StringIO() as stream:
        self.df.info(buf=stream)
        output = stream.getvalue()
        text_widget.insert(tk.END, output)
    text_widget.config(state="disabled")
            
    # 左侧第二个文本组件
    text_widget2 = tk.Text(new_window, bd=2, relief=tk.GROOVE, width=70, height=22)
    text_widget2.grid(row=1, column=0, padx=15, pady=5, sticky="sw")
         
    # 创建右侧容器frame,统一管理右侧组件
    right_frame = tk.Frame(new_window, bd=0)
    right_frame.grid(row=0, column=1, padx=15, pady=10, rowspan=2, sticky="n")

    # 右侧第一个文本组件
    text_widget3 = tk.Text(right_frame, bd=2, relief=tk.GROOVE, width=80, height=3)
    text_widget3.grid(row=0, column=0, sticky="nw", pady=(0, 5))  # 缩小下方间距

    # 输入框框架
    inputs_frame = tk.Frame(right_frame, bd=2, relief=tk.GROOVE, width=text_widget3["width"])
    inputs_frame.grid(row=1, column=0, sticky="nw", pady=(0, 5))  # 紧贴text_widget3

    # 输入框内容
    label1 = tk.Label(inputs_frame, text="Label 1:")
    label1.grid(row=0, column=0, padx=5, pady=5, sticky="w")
    input1 = tk.Entry(inputs_frame)
    input1.grid(row=0, column=1, padx=5, pady=5, sticky="w")

    label2 = tk.Label(inputs_frame, text="Label 2:")
    label2.grid(row=1, column=0, padx=5, pady=5, sticky="w")
    input2 = tk.Entry(inputs_frame)
    input2.grid(row=1, column=1, padx=5, pady=5, sticky="w")

    add_button = tk.Button(inputs_frame, text="Add", width=10)
    add_button.grid(row=2, column=0, columnspan=2, pady=10)

    # 添加新的text_widget4
    text_widget4 = tk.Text(right_frame, bd=2, relief=tk.GROOVE, width=80, height=10)
    text_widget4.grid(row=2, column=0, sticky="nw", pady=(0, 10))
    # 设置为不可编辑(按需调整)
    text_widget4.config(state="disabled")

修改说明

  1. 创建右侧容器:新增right_frame作为右侧所有组件的容器,放在new_window的column1,rowspan=2确保占据左侧两行高度,sticky="n"让容器顶部对齐,内部组件独立控制垂直布局。
  2. 缩小垂直间距:将text_widget3的pady设为(0,5),inputs_frame的pady设为(0,5),大幅压缩两者之间的空白,实现紧贴效果。
  3. 添加text_widget4:在right_frame的row2位置添加该组件,设置合适高度和间距,置于inputs_frame正下方。
  4. 对齐优化:所有右侧组件的sticky设为"nw",确保左对齐,保持布局一致性。

内容的提问来源于stack exchange,提问作者Param Dhingana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 01:04:53