问题
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.bbox
is useless, because it's the dimension you want to layout this widget.Using a fixed
width=200
, smaller thanfm_grid.width
will allways cut thefm_grid
content, it's not dynamically either.canvas.configure(scrollregion=canvas.bbox("all"),width=200,height=200)
How to sync the
width
of theCanvas
with thewidth
of theFrame
inside?
- You bound
fm_grid.bind("<Configure>"
, therefore theevent.widget
isfm_grid
, theFrame
inside. - Get the dimensions of the
event.widget
from therew.winfo_...
and build abbox
tuple to setscrollregion
. Use
width
to 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