1

I'm working on a Tkinter GUI. I want to make two separate frames have the same width so that they line up vertically. I do not know of any way to put them inside the same structure because they need to be independently scrollable in the vertical direction (that functionality is not yet in the code).

I tried various ways of what I thought was setting the lower frame width equal to the upper frame width because the lower frame has a smaller width by default, but that seems to have no effect. See lines

        # Match widths
        self.vert_frames[-1][1].configure(width=self.vert_frames[-1][0].cget("width"))

I'm new to both stackoverflow and python, so let me know if you need more details or have corrections to my question formatting or anything else. I've been a longtime reader, so I'm excited to hear what solutions you all know about!

Thank you all in advance.

# Imports

import tkinter as tk
from tkinter import ttk

# Define GUI CLASS
class tl_GUI:
    # initialize the GUI
    def __init__(self, root):
        self.root = root
        
        # set geometry
        # self.root.geometry("480x320+150+150") # remove if not used in final version
        self.root.grid_rowconfigure(0, weight=1)
        self.root.grid_columnconfigure(0, weight=1)
        
        # SET STRUCTURE
        # create data_canvas
        self.data_canvas = tk.Canvas(self.root)
        self.data_canvas.grid(row = 0, column = 0, sticky = "nsew")
        
        # create 2-pane PanedWindow
        self.data_panedwindow = ttk.Panedwindow(self.data_canvas, orient="vertical")
        self.data_panedwindow.pack(fill="both", expand=True)
        
        # create input canvas
        self.in_canvas = tk.Canvas(self.data_panedwindow)
        self.data_panedwindow.add(self.in_canvas, weight=1)
        
        # create input frame
        self.in_frame = ttk.Frame(self.in_canvas, relief="sunken")
        self.in_frame.pack()
        
        # create output canvas
        self.out_canvas = tk.Canvas(self.data_panedwindow)
        self.data_panedwindow.add(self.out_canvas, weight=1)
        
        # create output frame
        self.out_frame = ttk.Frame(self.out_canvas, relief="sunken")
        self.out_frame.pack()
        
        # CREATE INITIAL I/O FRAMES
        self.curr_compares = 0
        self.vert_frames = []
        for init_frames in range(0, 2):
            self.add_compareIO()
    
    # define method to add a vertical I/O frame
    def add_compareIO(self):
        # create input and output frames
        self.vert_frames.append([])
        self.vert_frames[-1].append(ttk.Frame(self.in_frame, padding = 2, relief = "groove"))
        self.vert_frames[-1].append(ttk.Frame(self.out_frame, padding = 2, relief = "groove"))
        self.vert_frames[-1][0].grid(row = 0, column = self.curr_compares)
        self.vert_frames[-1][1].grid(row = 0, column = self.curr_compares)
        
        # close_frame
        col = len(self.vert_frames)-1 # may be able to use self.curr_compares instead
        self.vert_frames[-1][0].button_close = ttk.Label(self.vert_frames[-1][0], 
                                                          text="[Image here]")
        self.vert_frames[-1][0].button_close.grid(row = 0, column = 0, columnspan=2, stick = "e")
        self.vert_frames[-1][0].button_close.bind("<Button-1>", 
                                          lambda e: self.destroy_frame(col_num=col))
        self.vert_frames[-1][1].button_close = ttk.Label(self.vert_frames[-1][1], 
                                                          text="[Image here]")
        self.vert_frames[-1][1].button_close.grid(row = 0, column = 0, columnspan=2, stick = "e")
        self.vert_frames[-1][1].button_close.bind("<Button-1>", 
                                          lambda e: self.destroy_frame(col_num=col))
        
        # populate inputs
        self.vert_frames[-1][0].label_hpp = ttk.Label(self.vert_frames[-1][0], text = "INPUT1")
        self.vert_frames[-1][0].entry_hpp = ttk.Entry(self.vert_frames[-1][0], width = 13)
        self.vert_frames[-1][0].entry_hpp.bind("<KeyRelease>", lambda e: self.refresh_calculations(col)) # recalculate when any keyboard button is pressed
            
        self.vert_frames[-1][0].label_int_rate = ttk.Label(self.vert_frames[-1][0], text = "INPUT2")
        self.vert_frames[-1][0].entry_int_rate = ttk.Entry(self.vert_frames[-1][0], width = 13)
        self.vert_frames[-1][0].entry_int_rate.bind("<KeyRelease>", lambda e: self.refresh_calculations(col))
        
        self.vert_frames[-1][0].label_RENAME = ttk.Label(self.vert_frames[-1][0], text = "INPUT3")
        self.vert_frames[-1][0].entry_RENAME = ttk.Entry(self.vert_frames[-1][0], width = 13)
        self.vert_frames[-1][0].entry_RENAME.bind("<KeyRelease>", lambda e: self.refresh_calculations(col))
            
        self.vert_frames[-1][0].label_hpp.grid(row = 1, column = 0)
        self.vert_frames[-1][0].entry_hpp.grid(row = 1, column = 1)
        self.vert_frames[-1][0].label_int_rate.grid(row = 2, column = 0)
        self.vert_frames[-1][0].entry_int_rate.grid(row = 2, column = 1)
        self.vert_frames[-1][0].label_RENAME.grid(row = 3, column = 0)
        self.vert_frames[-1][0].entry_RENAME.grid(row = 3, column = 1)
        
        # populate outputs
        self.vert_frames[-1][1].label_tcl = ttk.Label(self.vert_frames[-1][1], text = "OUTPUT1: {}".format(10))
        
        self.vert_frames[-1][1].label_tcl.grid(row = 1, column = 0)
        
        # Match widths
        self.vert_frames[-1][1].configure(width=self.vert_frames[-1][0].cget("width"))
        
        # update counter
        self.curr_compares += 1
        
    def destroy_frame(self, col_num):
        self.vert_frames[col_num][0].grid_forget()
        self.vert_frames[col_num][1].grid_forget()
        self.vert_frames[col_num][0].destroy()
        self.vert_frames[col_num][1].destroy()
        self.vert_frames[col_num] = []
        
    
    # define method to refresh calculations (wrapper for actual calcs)
    def refresh_calculations(self, col):
        pass
    
    
# Execute code
if __name__ == "__main__":
    root = tk.Tk()
    my_gui = tl_GUI(root)
    root.mainloop()
  • Does this help ? https://stackoverflow.com/questions/63189654/trouble-using-tkinter-grid/63191526#63191526 – Thingamabobs Aug 08 '20 at 19:10
  • if you want to put widget on canvas then you should rather use `canvas.create_window(position, widget`)` instead of `grid()`/`pack()`/`place()` – furas Aug 08 '20 at 21:49
  • It's very hard to give a good answer. Questions about layout depend greatly on what else is in the window and how you want the window to behave. For example, currently neither frame fills the window if you make the window larger. Do you want them to? Are you planning on putting more widgets on the left or the right, or do you want there to be blank space? – Bryan Oakley Aug 08 '20 at 23:02
  • @Atlas435 :That's a good thought, but the "container frame".cget("width") returns a string '0' (sometimes...other times returns an odd tk class - this seems to be a bug with tkinter). If cget("width") actually returned the width in pixels, I wouldn't be having a problem. – IDoEngineering Aug 09 '20 at 18:59
  • @furas: I don't think I knew about that. I'll look into that further! Thanks! (It's not a solution, but may render the question moot.) – IDoEngineering Aug 09 '20 at 19:00
  • @BryanOakley: I don't want the input and output frames to expand when the window size is changed, although I do want the paned window to fill the application window. In the full version of this code, I have a clickable "plus" icon on the right that adds another input/output column on the right. I only posted a vanilla version of the code that isolated my conundrum. I think my big problem is not being able to find the width of the input frame. If I knew that, I think I could pretty easily set the width of the output frame equal to it. – IDoEngineering Aug 09 '20 at 19:08
  • @IDoEngineering I need to update this answer on the posting because on locations that I don't want to to be resized at all I add `frame_id.grid_propagate()` or `.pack_propagate()`. So my frame do not be affected by the children it carries. – Thingamabobs Aug 09 '20 at 20:07

0 Answers0