I am building an Automated Data Preprocessing tool in Python where I am using Tkinter for the GUI, In the new_window, which is a TopLevel Window I want to shrink the vertical space that is unoccupied between inputs_frame and the text_widget3, and I want to place this inputs_frame right below the text_widget3. And thereafter I want to add another text_widget4 right below the inputs_frame.
Here is the code for this new window
def open_new_window(self):
new_window = tk.Toplevel()
new_window.title("New Window")
# Set the window size to full screen
# Set the window size to full screen
new_window.state('zoomed')
# Create a text widget to display the info
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")
# Redirect the output of df.info() to the text widget
with io.StringIO() as stream:
self.df.info(buf=stream)
output = stream.getvalue()
text_widget.insert(tk.END, output)
# Make the text widget uneditable
text_widget.config(state="disabled")
# Create a text widget to display the info
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")
# Create another text widget to display additional info
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")
# Add a frame to the window for inputs
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")
# Add labels and text inputs to the inputs frame
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 an "Add" button to the inputs frame
add_button = tk.Button(inputs_frame, text="Add", width=10)
add_button.grid(row=2, column=0, columnspan=2, pady=10)
Here is an output screenshot of the window after running the code -
I also have tried certain methods like changing the weights of the rows using.grid_rowconfigure() method, but even that didn't work!
And here is the full code for the whole program until now!
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")
# Top layout with title
self.title_label = tk.Label(self.root, text="Data Wizard: Automated Data Preprocessing", font=("Arial", 18))
self.title_label.pack(pady=20)
# Middle layout with table frame
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)
# Create a treeview widget to display table
self.tree = ttk.Treeview(self.table_frame, selectmode='browse')
self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# Add scrollbar to the treeview widget
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)
# Bottom layout with Upload CSV file label and button
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)
# Add button to open a new window
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):
# Open file dialog to select a CSV file
file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])
if file_path:
# Read CSV file as pandas dataframe
self.df = pd.read_csv(file_path)
# Set the columns of the treeview widget based on the dataframe columns
self.tree["columns"] = list(self.df.columns)
# Set column headings and widths based on the dataframe
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)
# Insert data into treeview widget
for i, row in self.df.iterrows():
self.tree.insert("", "end", values=list(row))
# Change the upload label to the filename
self.upload_label.config(text=file_path)
# Add horizontal scrollbar to the treeview widget
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")
# Set the window size to full screen
# Set the window size to full screen
new_window.state('zoomed')
# Create a text widget to display the info
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")
# Redirect the output of df.info() to the text widget
with io.StringIO() as stream:
self.df.info(buf=stream)
output = stream.getvalue()
text_widget.insert(tk.END, output)
# Make the text widget uneditable
text_widget.config(state="disabled")
# Create a text widget to display the info
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")
# Create another text widget to display additional info
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")
# Add a frame to the window for inputs
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")
# Add labels and text inputs to the inputs frame
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 an "Add" button to the inputs frame
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()
I think the easiest solution is to put the widgets on the right into a frame, and then put the frame to the right of the other two windows.
Since it appears you don't need a grid for the two main sections on the right, I would use pack
for them.
In the following example I create a frame named f
. It is used as the first argument when creating text_widget3
and inputs_frame
. Those two are then packed inside the frame.
f = tk.Frame(new_window)
...
f.grid(row=0, column=1, padx=15, pady=10, rowspan=2, sticky="nsew")
text_widget3 = tk.Text(f, bd=2, relief=tk.GROOVE, width=80, height=3)
inputs_frame = tk.Frame(f, bd=2, relief=tk.GROOVE, width=text_widget3["width"])
text_widget3.pack(side="top", fill="x")
inputs_frame.pack(side="top", fill="x")
# Add labels and text inputs to the inputs frame
label1 = tk.Label(inputs_frame, text="Label 1:")
input1 = tk.Entry(inputs_frame)
label2 = tk.Label(inputs_frame, text="Label 2:")
input2 = tk.Entry(inputs_frame)
add_button = tk.Button(inputs_frame, text="Add", width=10)
label1.grid(row=0, column=0, padx=5, pady=5, sticky="w")
input1.grid(row=0, column=1, padx=5, pady=5, sticky="w")
label2.grid(row=1, column=0, padx=5, pady=5, sticky="w")
input2.grid(row=1, column=1, padx=5, pady=5, sticky="w")
add_button.grid(row=2, column=0, columnspan=2, pady=10)