Python Tkinter使用画布动态创建带有滚动条的窗口 [英] Python tkinter use canvas to create dynamically window with scroll bar
问题描述
我的目标是解决网格超出窗口的问题(如图1所示)
不要:
删除fm_grid.pack()
,使用以下代码进行布局:canvas.create_window(...
.
另外,我建议不使用偏移量(4,4)
,因为您必须在每个canvas.configure(...,width = width + 4
.请改用(0,0)
.#fm_grid.pack()...canvas.create_window((4,4),window = fm_grid,anchor ='nw')
没用,用于动态创建窗口:
-
您对
canvas.bbox
的使用是无用的,因为这是您要布局此小部件的尺寸. -
使用小于
fm_grid.width
的固定width = 200
,将始终剪切fm_grid
内容,也不是动态.canvas.configure(scrollregion = canvas.bbox("all"),width = 200,height = 200)
如何将
Canvas
的width
与内部Frame
的width
进行同步?
- 您绑定了
fm_grid.bind(< Configure>"
,因此event.widget
是fm_grid
,里面的Frame
. - 从那里
w.winfo _...
获取event.widget
的尺寸,并构建一个bbox
元组以设置滚动区域
. -
使用
width
设置canvas.width
,使其与event.widget.winfo_width()
同步./p>Class ScrollCanvas(tk.Canvas):def __init __(self,parent,** kwargs):super().__ init __(parent,** kwargs)def create_window(自己,孩子):super().create_window((0,0),window = child,anchor ='nw')child.bind(< Configure>",self.on_configure)def on_configure(自我,事件):w = event.widgetbbox = x,y,宽度,高度= 0、0,w.winfo_width(),w.winfo_height()self.configure(scrollregion = bbox,width = width)
使用Python测试:3.5-'TclVersion':8.6'TkVersion':8.6
My objective is to solve the problem of the grid exceeding the window(shown as figure.1)
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()
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
这篇关于Python Tkinter使用画布动态创建带有滚动条的窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!