Python tkinter 使用 canvas 动态创建 window 带滚动条
Python tkinter use canvas to create dynamically window with scroll bar
我的objective是解决网格超出window的问题(如图1)
enter image description here
我的程序功能是创建一个由用户定义的列数的网格。
我尝试使用canvas来解决这个问题,但仍然没有成功。
canvas中没有显示完整的网格。(如图2)
enter image description here
下面是我的代码,请大家帮忙解决问题或者给我一些建议。
非常感谢。
代码:
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()
Question: It doesn't show the full grid in the canvas
您必须将 Canvas
的 width
与 Frame
的 width
同步。
Note: fm_grid = tk.Frame(canvas, bg='blue')
is shown in 'blue'
.
Dont's:
Remove fm_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 every canvas.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:
您对 canvas.bbox
的使用没有用,因为它是您要布置此小部件的维度。
使用固定的width=200
,小于fm_grid.width
会总是剪切 fm_grid
的内容,它是也不是动态的。
canvas.configure(scrollregion=canvas.bbox("all"),width=200,height=200)
How to sync the width
of the Canvas
with the width
of the Frame
inside?
- 你绑定了
fm_grid.bind("<Configure>"
,所以event.widget
是fm_grid
,里面的Frame
。
- 从那里获取
event.widget
的维度 w.winfo_...
并构建一个 bbox
元组来设置 scrollregion
。
使用width
设置canvas.width
,与event.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)
测试 Python:3.5 - 'TclVersion':8.6 'TkVersion':8.6
我的objective是解决网格超出window的问题(如图1)
enter image description here
我的程序功能是创建一个由用户定义的列数的网格。
我尝试使用canvas来解决这个问题,但仍然没有成功。 canvas中没有显示完整的网格。(如图2) enter image description here
下面是我的代码,请大家帮忙解决问题或者给我一些建议。 非常感谢。
代码:
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()
Question: It doesn't show the full grid in the canvas
您必须将 Canvas
的 width
与 Frame
的 width
同步。
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:
您对
canvas.bbox
的使用没有用,因为它是您要布置此小部件的维度。使用固定的
width=200
,小于fm_grid.width
会总是剪切fm_grid
的内容,它是也不是动态的。canvas.configure(scrollregion=canvas.bbox("all"),width=200,height=200)
How to sync the
width
of theCanvas
with thewidth
of theFrame
inside?
- 你绑定了
fm_grid.bind("<Configure>"
,所以event.widget
是fm_grid
,里面的Frame
。 - 从那里获取
event.widget
的维度w.winfo_...
并构建一个bbox
元组来设置scrollregion
。 使用
width
设置canvas.width
,与event.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)
测试 Python:3.5 - 'TclVersion':8.6 'TkVersion':8.6