Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Tkinter pack not resizing frame embedded in canvas

I’m trying to make scrollable frame in Tkinter that prompts the user to type something, which then adds the phrase and a new row upon pressing Enter. For some reason, the frame within the canvas doesn’t seem to be resizing after adding 4 rows, even though I’m using pack to add the new row. I tried adding a height parameter to the row Frames, but it didn’t seem to change anything. Is there a problem with how I’m configuring the scroll bar?

import tkinter as tk

class TermDisplayFrame(tk.Frame):
    def __init__(self, parent, width=100, height=50):
        super().__init__(parent)
        self.canvas = tk.Canvas(self)
        self.frame = tk.Frame(self.canvas)
        self.canvas.create_window((0,0), window = self.frame, anchor=tk.NW, tags='frame')

        self.canvas.pack(side='left')
        self.scroll = tk.Scrollbar(self,orient='vertical')  
        self.canvas.configure(xscrollcommand=self.scroll.set)
        self.scroll.pack(side='right',fill='y')
        self.scroll.config(command=self.canvas.yview)
        self.canvas.bind("<Configure>", lambda e: self.onCanvasConfigure(e, self.canvas))

        self.initialize_header()
        self.initialize_entry()

    def onCanvasConfigure(self,e, widget):
        self.canvas.itemconfig('frame', height=self.canvas.winfo_height(), width=self.canvas.winfo_width())
        print('Configure triggered')


    def reset_scroll_region(self,event=False):
        self.canvas.configure(scrollregion=self.canvas.bbox('all'))

    def initialize_header(self):
        row = tk.Frame(self.frame)
        tk.Label(row, width=5, text='Term', borderwidth='2', relief='groove').pack(side='left', fill='both', expand=True)
        tk.Label(row, width=5, text='Meaning', borderwidth='2', relief='groove').pack(side='left', fill='both', expand=True)
        tk.Label(row, width=5, text='Apply to\n\n', borderwidth='2', relief='groove').pack(side='left', fill='both', expand=True)
        tk.Label(row, width=5, text='Times', borderwidth='2', relief='groove').pack(side='left', fill='both', expand=True)
        row.pack(side='top', fill='x')

    def initialize_entry(self):
        self.recent_row = tk.Frame(self.frame)
        self.entry = tk.Entry(self.recent_row, width=5, borderwidth='2', relief='groove')
        self.entry.pack(side='left', fill='both', expand=True)
        tk.Label(self.recent_row, width=5, text='replaced by', borderwidth='2', relief='groove').pack(side='left', fill='both', expand=True)
        tk.Label(self.recent_row, width=5, text='Apply to\n\n', borderwidth='2', relief='groove').pack(side='left', fill='both', expand=True)
        tk.Label(self.recent_row, width=5, text='Times', borderwidth='2', relief='groove').pack(side='left', fill='both', expand=True)
        self.recent_row.pack(side='top', fill='x')
        self.entry.bind("<Return>", self.add_row)

    def add_row(self, event):
        text = self.entry.get()
        self.entry.forget()
        tk.Label(self.recent_row, width=5, text=text, borderwidth='2', relief='groove').pack(side='left', fill='both', expand=True)
        self.initialize_entry()
        self.reset_scroll_region()
        print(self.frame.winfo_children())
        print(self.frame.winfo_height())

if __name__ == "__main__":
    root=tk.Tk()
    TermDisplayFrame(root).pack()
    root.mainloop()

>Solution :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

There are few issues in your code:

  • self.canvas.configure(xscrollcommand=self.scroll.set) should be self.canvas.configure(yscrollcommand=self.scroll.set) instead

  • you have reset the frame height inside onCanvasConfigure(). Change self.canvas.itemconfig('frame', height=self.canvas.winfo_height(), width=self.canvas.winfo_width()) to self.canvas.itemconfig('frame', width=self.canvas.winfo_width()) instead

  • you need to call self.frame.update_idletasks() to update the frame before calling self.canvas.configure(scrollregion=self.canvas.bbox('all')) inside reset_scroll_region()

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading