问题
My objective is to solve the problem of the grid exceeding the window(shown as figure.1)
enter image description here
My program function is creating a grid that number of columns defined by user.
I tried using canvas to solve this problem, but it still doesn't work successfully. It doesn't show the full grid in the canvas.(shown as figure.2) enter image description here
Below is my code, could you please help solve the problems or give me some advice. Thanks a lot.
Code:
import tkinter as tk
import tkinter.messagebox
import tkinter.filedialog
MainWindow = tk.Tk()
MainWindow.title('Helloworld')
MainWindow.geometry('1000x800')
def btn_generate():
global EntryNamelist
global Entrycoordinatelist
global EntryLabellist
con_num = en_condition_num.get()
if con_num != '':
#### Grid Body
for i in range(1,int(con_num) +1 ):
lb_name = tk.Label(fm_grid, text="Condition" + str(i) )
lb_name.grid(row=i, column=0, padx=2, pady=1, ipadx=20, ipady=5)
En_name = tk.Entry(fm_grid, bd = 2,width = 10,font=('Ubuntu', 10))
En_name.grid(row=i, column=1, padx=2, pady=1, ipadx=35, ipady=5)
En_coor = tk.Entry(fm_grid, bd = 2,width = 10,font=('Ubuntu', 10))
En_coor.grid(row=i, column=2, padx=2, pady=1, ipadx=200, ipady=5)
else:
tk.messagebox.showerror("Error", "Please input a num of conditions")
fm_main = tk.Frame()
fm3 = tk.Frame(fm_main)
lb_condition = tk.Label(fm3,text = 'Please input the number of condition')
lb_condition.pack(side="left")
en_condition_num = tk.Entry(fm3, bd = 2,width = 5)
en_condition_num.pack()
fm3.pack()
btn_generate = tk.Button(fm_main,text="Generate Grid",command=btn_generate)
btn_generate.pack()
lb_en = tk.Label(fm_main,text = '')
lb_en.pack()
def myfunction(event):
canvas.configure(scrollregion=canvas.bbox("all"),width=200,height=200)
canvas=tk.Canvas(fm_main)
fm_grid = tk.Frame(canvas)
fm_grid.pack()
myscrollbar=tk.Scrollbar(fm_main,orient="vertical",command=canvas.yview)
canvas.configure(yscrollcommand=myscrollbar.set)
myscrollbar.pack(side="right",fill="y")
canvas.pack(side="left")
canvas.create_window((4,4),window=fm_grid,anchor='nw')
fm_grid.bind("<Configure>",myfunction)
fm_main.pack()
MainWindow.mainloop()
回答1:
Question: It doesn't show the full grid in the canvas
You have to sync, the width of the Canvas with the width of the Frame inside.
Note:
fm_grid = tk.Frame(canvas, bg='blue')is shown in'blue'.
Dont's:
Removefm_grid.pack(), you layout with:canvas.create_window(....
Also, i recommend not to use a offset(4, 4), because you have to calculate with this offset on everycanvas.configure(..., width=width + 4. Use(0, 0)instead.# fm_grid.pack() ... canvas.create_window((4,4),window=fm_grid,anchor='nw')
Useless, to create dynamically window:
Your usage of
canvas.bboxis useless, because it's the dimension you want to layout this widget.Using a fixed
width=200, smaller thanfm_grid.widthwill allways cut thefm_gridcontent, it's not dynamically either.canvas.configure(scrollregion=canvas.bbox("all"),width=200,height=200)
How to sync the
widthof theCanvaswith thewidthof theFrameinside?
- You bound
fm_grid.bind("<Configure>", therefore theevent.widgetisfm_grid, theFrameinside. - Get the dimensions of the
event.widgetfrom therew.winfo_...and build abboxtuple to setscrollregion. Use
widthto setcanvas.width, to be in sync with theevent.widget.winfo_width().class ScrollCanvas(tk.Canvas): def __init__(self, parent, **kwargs): super().__init__(parent, **kwargs) def create_window(self, child): super().create_window((0, 0), window=child, anchor='nw') child.bind("<Configure>", self.on_configure) def on_configure(self, event): w = event.widget bbox = x, y, width, height = 0, 0, w.winfo_width(), w.winfo_height() self.configure(scrollregion=bbox, width=width)Tested with Python: 3.5 - 'TclVersion': 8.6 'TkVersion': 8.6
来源:https://stackoverflow.com/questions/58166128/python-tkinter-use-canvas-to-create-dynamically-window-with-scroll-bar