Tkinter:在画布窗口中嵌入填充的帧
由于tkinter框架小部件不支持滚动,我的初学者自己决定探索使用画布来容纳先前填充的框架的可能性。在下面重现的代码中,有两个问题我无法解决:为什么最左上方的小部件占用如此大的空间;为什么应用程序占用了所有可用的屏幕空间,甚至缩短了小部件,因此没有显示滚动滑块。欢迎所有建议Tkinter:在画布窗口中嵌入填充的帧,tkinter,scrollbar,python-3.7,tkinter-canvas,Tkinter,Scrollbar,Python 3.7,Tkinter Canvas,由于tkinter框架小部件不支持滚动,我的初学者自己决定探索使用画布来容纳先前填充的框架的可能性。在下面重现的代码中,有两个问题我无法解决:为什么最左上方的小部件占用如此大的空间;为什么应用程序占用了所有可用的屏幕空间,甚至缩短了小部件,因此没有显示滚动滑块。欢迎所有建议 #!/usr/bin/env python3 from tkinter import * class Calc_Table(Frame): def __init__(self, root, cols, rows):
#!/usr/bin/env python3
from tkinter import *
class Calc_Table(Frame):
def __init__(self, root, cols, rows):
Frame.__init__(self, master=root)
self.cols = cols
self.rows = rows
hscrollbar = Scrollbar(orient=HORIZONTAL)
hscrollbar.grid(row = 1, column = 0, sticky = EW)
vscrollbar = Scrollbar(orient=VERTICAL)
vscrollbar.grid(row = 0, column = 1, sticky = NS)
self.canvas = Canvas(self, xscrollcommand = hscrollbar.set, yscrollcommand = vscrollbar.set,bg='yellow')
self.canvas.grid(row = 0, column = 0, sticky = NSEW)
self.canvas.grid_rowconfigure(0, weight = 1)
self.canvas.grid_columnconfigure(0, weight = 1)
hscrollbar.config(command = self.canvas.xview)
vscrollbar.config(command = self.canvas.yview)
self.initial_table = self.create_table(self.cols,self.rows)
self.canvas_frame = self.canvas.create_window(0, 0, window = self.initial_table,
width=400, height=200, anchor=NW)
self.canvas.update_idletasks()
self.canvas.config(scrollregion = self.canvas.bbox('all'))
def create_table(self, cols, rows): # build initial table ---->
self.cols, self.rows = cols, rows
for c in range(self.cols):
for r in range(self.rows):
if c == 0 and r == 0:
self.lbl = Label(self, width=6, height=1, bg="white",
text="? ? ?", relief=RAISED)
self.lbl.grid(column=c, row=r, padx=1, pady=1, sticky=NSEW)
elif c == 0 and r != 0:
self.lbl = Label(self, width=6, height=1, bg="white",
text=f"R{r}",relief=RAISED)
self.lbl.grid(column=c, row=r, padx=1, pady=1, sticky=NSEW)
elif c != 0 and r == 0:
self.lbl = Label(self, width=6, height=1, bg="white",
text=f"C{c}",relief=RAISED)
self.lbl.grid(column=c, row=r, padx=1, pady=1, sticky=NSEW)
else:
self.txt =Text(self, width=6, height=1, bg="white",
relief=SUNKEN)
self.txt.grid(column=c, row=r, padx=1, pady=1, sticky=NSEW)
for c in range(self.cols):
self.grid_columnconfigure(c, weight=1)
for r in range(self.rows):
self.grid_rowconfigure(r, weight=1)
if __name__ == '__main__':
cols = int(input("How many columns? "))
assert isinstance(int(cols), int), "integers only, please"
rows = int(input("How many rows? "))
assert isinstance(int(rows), int), "integers only, please"
root = Tk()
root.geometry("+10+10")
root.title("Master Table")
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)
my_table = Calc_Table(root, cols, rows)
my_table.grid(column=0, row=0, sticky=NSEW)
my_table.grid_columnconfigure(0, weight=1)
my_table.grid_rowconfigure(0, weight=1)
root.mainloop()
下面请查找已修改的代码,但画布中的框架和小部件仍无法展开:
from tkinter import *
class Calc_Table(Frame):
def __init__(self, root, cols, rows):
Frame.__init__(self, master=root)
self.cols = cols
self.rows = rows
hscrollbar = Scrollbar(orient=HORIZONTAL)
hscrollbar.grid(row = 1, column = 0, sticky = EW)
vscrollbar = Scrollbar(orient=VERTICAL)
vscrollbar.grid(row = 0, column = 1, sticky = NS)
self.canvas = Canvas(self, xscrollcommand = hscrollbar.set, yscrollcommand = vscrollbar.set, bg='yellow')
self.canvas.grid(row = 0, column = 0, sticky = NSEW)
self.canvas.grid_rowconfigure(0, weight = 1)
self.canvas.grid_columnconfigure(0, weight = 1)
hscrollbar.config(command = self.canvas.xview)
vscrollbar.config(command = self.canvas.yview)
self.table_frame = self.create_table(self.cols,self.rows)
self.canvas_frame = self.canvas.create_window(0, 0, window = self.table_frame, anchor=NW)
self.canvas.update_idletasks()
self.canvas.config(scrollregion = self.canvas.bbox('all'))
print(self.canvas.find_all()) #check canvas slaves
print(len(self.table_frame.grid_slaves())) #check table_frame slaves
def create_table(self, cols, rows): # build initial table ---->
self.table_frame = Frame(self.canvas)
self.table_frame.grid(column = 0, row = 0, sticky = NSEW)
self.cols, self.rows = cols, rows
for c in range(self.cols):
for r in range(self.rows):
if c == 0 and r == 0:
self.lbl = Label(self.table_frame, width=6, height=1, bg="white",text="? ? ?", relief=RAISED)
self.lbl.grid(column=c, row=r, padx=1, pady=1,sticky=NSEW)
elif c == 0 and r != 0:
self.lbl = Label(self.table_frame, width=6, height=1, bg="white", text=f"R{r}",relief=RAISED)
self.lbl.grid(column=c, row=r, padx=1, pady=1,sticky=NSEW)
elif c != 0 and r == 0:
self.lbl = Label(self.table_frame, width=6, height=1, bg="white",text=f"C{c}",relief=RAISED)
self.lbl.grid(column=c, row=r, padx=1, pady=1,sticky=NSEW)
else:
self.txt =Text(self.table_frame, width=6, height=1, bg="white", relief=SUNKEN)
self.txt.grid(column=c, row=r, padx=1, pady=1,sticky=NSEW)
self.table_frame.grid_columnconfigure(0, weight=1)
self.table_frame.grid_rowconfigure(0, weight=1)
for c in range(self.cols):
self.table_frame.grid_columnconfigure(c, weight=1)
for r in range(self.rows):
self.table_frame.grid_rowconfigure(r, weight=1) # end table
return self.table_frame
if __name__ == '__main__':
cols = int(input("How many columns? "))
assert isinstance(int(cols), int), "integers only, please"
rows = int(input("How many rows? "))
assert isinstance(int(rows), int), "integers only, please"
root = Tk()
root.geometry("+10+10")
root.title("Master Table")
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)
my_table = Calc_Table(root, cols, rows)
my_table.configure(bg = "green")
my_table.grid(column=0, row=0, sticky=NSEW)
my_table.grid_columnconfigure(0, weight=1)
my_table.grid_rowconfigure(0, weight=1)
root.mainloop()
为什么最左上方的小部件占用如此大的空间
主要原因是画布位于self
的第0行、第0列,画布的默认大小约为200像素。如果更改画布的高度,您将看到行的大小更改的幅度相同
另一个问题是,您在create\u table
中创建的所有小部件都被赋予self
作为主部件。如果您试图创建一个可滚动的表格,那么这些表格必须是画布内框架的子项
为什么应用程序占用了所有可用的屏幕空间,甚至缩短了小部件,因此没有显示滚动滑块
出于与之前相同的原因-create_table
将小部件放在根窗口中,并将它们放在与滚动条相同的行和列中
你做错的最根本的事情是你没有在画布中创建一个框架。您需要在
create_table
中创建一个框架,将create_table
中的所有其他小部件放在该框架内,然后确保create_table
返回该框架
def create_table(self, cols, rows):
table_frame = Frame(self.canvas)
...
self.lbl = Label(table_frame, ...)
...
return table_frame
有些缩进是你的代码是正确的。范围内的r(self.rows)应该处于什么级别?我按照您的建议更改了代码;毫不奇怪,它确实起了作用。不幸的是,为了获得滚动效果,会丢失扩展:画布中的帧及其子帧不会扩展,即使我在适当的地方喷涂了grid_columnconfigure和grid_rowconfigure。谢谢您的支持。@user2328909:框架应该展开或收缩以适合其内容,除非您正在采取措施防止这种情况发生。但是,您明确设置了内部框架的大小,因此它不能增长或收缩。我确实删除了大小参数,但结果是相同的。我还编辑了第一篇文章,以便添加代码的修订版本。我深入研究了一下,发现需要一个canvas itemconfig,以使内部框架的大小与canvas的大小保持一致。工作完成了。这是无价的帮助。