调整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")
修改说明
- 创建右侧容器:新增
right_frame作为右侧所有组件的容器,放在new_window的column1,rowspan=2确保占据左侧两行高度,sticky="n"让容器顶部对齐,内部组件独立控制垂直布局。 - 缩小垂直间距:将
text_widget3的pady设为(0,5),inputs_frame的pady设为(0,5),大幅压缩两者之间的空白,实现紧贴效果。 - 添加text_widget4:在
right_frame的row2位置添加该组件,设置合适高度和间距,置于inputs_frame正下方。 - 对齐优化:所有右侧组件的
sticky设为"nw",确保左对齐,保持布局一致性。
内容的提问来源于stack exchange,提问作者Param Dhingana
相关产品推荐
相关产品推荐

