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()
CodePudding user response:
There are few issues in your code:
self.canvas.configure(xscrollcommand=self.scroll.set)
should beself.canvas.configure(yscrollcommand=self.scroll.set)
insteadyou have reset the frame height inside
onCanvasConfigure()
. Changeself.canvas.itemconfig('frame', height=self.canvas.winfo_height(), width=self.canvas.winfo_width())
toself.canvas.itemconfig('frame', width=self.canvas.winfo_width())
insteadyou need to call
self.frame.update_idletasks()
to update the frame before callingself.canvas.configure(scrollregion=self.canvas.bbox('all'))
insidereset_scroll_region()