Tkinter:Canvas 中的可滚动框架:自动调整大小绑定错误
Tkinter: scrollable Frame in Canvas: Auto-resize binding error
此脚本在 运行 时打开一个 window,分为 3 个框架:
- 将在其中显示数据的大框架(标签小部件)。
- 下方有一个较小的框架,带有用户输入小部件。
- 右下角带有文本框小部件的小框架。
大框架将包含大量数据(= 标签小部件),因此我需要它可滚动(垂直)。
这是我通过在滚动条小部件旁边创建一个 canvas 小部件来完成的。在canvas中放置了一个框架小部件。
似乎一切正常,但我的调整大小功能不起作用。
我的框架小部件没有更新其尺寸!这可能是因为我无法修复的错误。
基本问题:
脚本在第 43 行的“lambda: resize_frame(self)”命令中出错。我该如何解决这个问题?
旁注: 我的问题可能更多地与 canvas 小部件上的不正确绑定有关。因为我不确定我是否想要提供足够的上下文(脚本)。
非常感谢。
from Tkinter import *
import math
class Processing(Toplevel):
def __init__(self, master, *args, **kwargs):
Toplevel.__init__(self, master)
self.master = master
self.title("Process Window")
for r in range(6):
self.rowconfigure(r, weight = 1)
for c in range(4):
self.columnconfigure(c, weight = 1)
### WINDOW size and position definitions ###
ScreenSizeX = master.winfo_screenwidth()
ScreenSizeY = ( master.winfo_screenheight() - 75 ) #about 75pixels for taskbar on bottom of screen (Windows)
ScreenRatio = 0.9
FrameSizeX = int(ScreenSizeX * ScreenRatio)
FrameSizeY = int(ScreenSizeY * ScreenRatio)
FramePosX = (ScreenSizeX - FrameSizeX)/2
FramePosY = (ScreenSizeY - FrameSizeY)/2
self.geometry("%sx%s+%s+%s"%(FrameSizeX,FrameSizeY,FramePosX,FramePosY))
### Creating 3 "sub-frames" ###
# Frame 1 - canvas container with scrollbar#
self.Canvas1 = Canvas(self, bg = "white")
self.Canvas1.grid(row = 0, column = 0, rowspan = 5, columnspan = 4, sticky = N+E+S+W)
self.Canvas1.rowconfigure(1, weight = 1)
self.Canvas1.columnconfigure(1, weight = 1)
self.myscrollbar=Scrollbar(self, orient = "vertical", command = self.Canvas1.yview)
self.Canvas1.configure(yscrollcommand = self.myscrollbar.set)
self.myscrollbar.grid(row = 0, column = 4, rowspan = 5, sticky = N+S)
# Frame 1 - Frame widget in canvas #
self.Frame1 = Frame(self.Canvas1, bg = "white")
self.Frame1.rowconfigure(0, weight = 1)
for c in range(2):
self.Frame1.columnconfigure(1 + (2 * c), weight = 1)#1,3 - columns for small icons in the future
for cb in range(3):
self.Frame1.columnconfigure((cb * 2), weight = 9)#0,2,4 - columns for data
self.CFrame1 = self.Canvas1.create_window(0, 0, window = self.Frame1, width = FrameSizeX, anchor = N+W)
self.Canvas1.bind("<Configure>", lambda: resize_frame(self)) # !!!!! Doesn't work & gives error !!!!!! #
self.Frame1.bind("<Configure>", lambda: scrollevent(self))
self.Canvas1.config(scrollregion=self.Canvas1.bbox("all"))
# Frame 2 #
self.Frame2 = Frame(self, bg= "yellow")
self.Frame2.grid(row = 5, column = 0, rowspan = 1, columnspan = 3, sticky = W+E+N+S)
for r in range(3):
self.Frame2.rowconfigure(r, weight=1)
for c in range(3):
self.Frame2.columnconfigure(c, weight = 1)
# Frame 3 #
self.Frame3 = Frame(self)
self.Frame3.grid(row = 5, column = 3, rowspan = 1, columnspan = 2, sticky = W+E+N+S)
self.Frame3.rowconfigure(0, weight = 1)
self.Frame3.columnconfigure(0, weight = 1)
# Propagation #
#self.grid_propagate(False) # All widgets (the 3 subframes) need to fit in Toplevel window. Minimal window size will be implemented later.
self.Canvas1.grid_propagate(False) # canvas works with scrollbar, widgets dont need to fit in window size.
#self.Frame1.grid_propagate(False) # Frame1 should resize to hold all data (label-widgets)
self.Frame2.grid_propagate(False) # fixed frame dimensions
self.Frame3.grid_propagate(False) # fixed textbox dimensions
self.Frame1.update_idletasks() # just to make sure
### Widgets for the multiple frames ###
# Frame1 - further populated by button command in frame 2#
self.lblaa = Label(self.Frame1, bg="white", text = "Processing...", justify = "left")
self.lblaa.grid(row = 0, column = 0, sticky = N+W)
self.LSlabelsr = []
self.LSlabelsa = []
self.LSlabelsb = []
# Frame 2 #
self.Wbuttontest=Button(self.Frame2, text="Start listing test", command = lambda: refresh(self))
self.Wbuttontest.grid(row = 0, column = 0, columnspan = 3)
self.Wentry = Entry(self.Frame2)
self.Wentry.grid(row = 2, column = 0, columnspan = 3, sticky = E+W, padx = 10)
self.Wentry.delete(0, END)
self.Wentry.insert(0, "user input here")
# Frame3 #
self.Wtext = Text(self.Frame3)
self.Wscrollb = Scrollbar(self.Frame3)
self.Wscrollb.config(command = self.Wtext.yview)
self.Wtext.config(yscrollcommand = self.Wscrollb.set)
self.Wtext.grid(row = 0, column = 0, sticky = N+E+W+S)
### Test-Lists ### Last character in the left column is "ez" !! ###
self.LSa = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
self.LSb = [1, 2, 3, 4, 66, 6, 7, 8, 9, 67, 11, 12, 13, 14, 68]
self.LSr = []
ib = 0
prefix = ""
for i in range(104):
if ib > 25:
prefix = chr(ord("a") + (i/ib - 1))
ib = 0
else:
pass
self.LSr.append(prefix + chr(97+ib))
ib += 1
### FUNCTIONS ###
def resize_frame(self, event):
self.Canvas1.itemconfig(self.CFrame1, width = e.width) #height of frame should depend on the contents.
def scrollevent(event):
self.Canvas1.configure(scrollregion=self.Canvas1.bbox("all"),width=200,height=200)
def refresh(self): ### Button-command: data will be shown ###
if self.lblaa.winfo_exists() == 1:
self.lblaa.destroy()
for i in range(len(self.LSr)):
self.Frame1.rowconfigure(i, weight = 0)
del self.LSlabelsr[:] # remove any previous labels from if the callback was called before
del self.LSlabelsa[:] # remove any previous labels from if the callback was called before
del self.LSlabelsb[:] # remove any previous labels from if the callback was called before
Vlabelheight = 1
# Left List #
for i in range(len(self.LSr)):
self.LSlabelsr.append(Label(self.Frame1, text = str(self.LSr[i]), bg = "LightBlue", justify = "left", height = Vlabelheight))
self.LSlabelsr[i].grid(row = i, column = 0, sticky = E+W)
# Middle List #
for i in range(len(self.LSa)):
self.LSlabelsa.append(Label(self.Frame1, text = str(self.LSa[i]), bg = "LightBlue", fg = "DarkViolet", justify = "left", height = Vlabelheight))
self.LSlabelsa[i].grid(row = i, column = 2, sticky = E+W)
# Right List #
for i in range(len(self.LSb)):
self.LSlabelsb.append(Label(self.Frame1, text = str(self.LSb[i]), bg = "LightBlue", fg = "DarkGreen", justify = "left", height = Vlabelheight))
self.LSlabelsb[i].grid(row = i, column = 4, sticky = E+W)
self.Frame1.update()
self.Frame1.update_idletasks()
print("done")
if __name__ == "__main__":
root = Tk()
root.title("Invisible")
root.resizable(FALSE,FALSE)
root.withdraw()
app = Processing(root)
root.mainloop()
R4PH4EL 建议后的工作版本:
- 正确缩进:函数被定义为 init 的一部分。
对第 43/107 和 44/110 行的 lambda 命令进行了一些调整。
from Tkinter import *
import math
class Processing(Toplevel):
def __init__(self, master, *args, **kwargs):
Toplevel.__init__(self, master)
self.master = master
self.title("Process Window")
for r in range(6):
self.rowconfigure(r, weight = 1)
for c in range(4):
self.columnconfigure(c, weight = 1)
### WINDOW size and position definitions ###
ScreenSizeX = master.winfo_screenwidth()
ScreenSizeY = ( master.winfo_screenheight() - 75 ) #about 75pixels for taskbar on bottom of screen (Windows)
ScreenRatio = 0.9
FrameSizeX = int(ScreenSizeX * ScreenRatio)
FrameSizeY = int(ScreenSizeY * ScreenRatio)
FramePosX = (ScreenSizeX - FrameSizeX)/2
FramePosY = (ScreenSizeY - FrameSizeY)/2
self.geometry("%sx%s+%s+%s"%(FrameSizeX,FrameSizeY,FramePosX,FramePosY))
### Creating 3 "sub-frames" ###
# Frame 1 - canvas container with scrollbar#
self.Canvas1 = Canvas(self, bg = "white")
self.Canvas1.grid(row = 0, column = 0, rowspan = 5, columnspan = 4, sticky = N+E+S+W)
self.Canvas1.rowconfigure(1, weight = 1)
self.Canvas1.columnconfigure(1, weight = 1)
self.myscrollbar=Scrollbar(self, orient = "vertical", command = self.Canvas1.yview)
self.Canvas1.configure(yscrollcommand = self.myscrollbar.set)
self.myscrollbar.grid(row = 0, column = 4, rowspan = 5, sticky = N+S)
# Frame 1 - Frame widget in canvas #
self.Frame1 = Frame(self.Canvas1, bg = "white")
self.Frame1.rowconfigure(0, weight = 1)
for c in range(2):
self.Frame1.columnconfigure(1 + (2 * c), weight = 1)#1,3 - columns for small icons in the future
for cb in range(3):
self.Frame1.columnconfigure((cb * 2), weight = 9)#0,2,4 - columns for data
self.CFrame1 = self.Canvas1.create_window(0, 0, window = self.Frame1, width = FrameSizeX, anchor = N+W)
self.Canvas1.bind("<Configure>", lambda event: self.resize_frame(event)) # !!!!! Doesn't work & gives error !!!!!! #
self.Frame1.bind("<Configure>", lambda event: self.scrollevent(event))
self.Canvas1.config(scrollregion=self.Canvas1.bbox("all"))
# Frame 2 #
self.Frame2 = Frame(self, bg= "yellow")
self.Frame2.grid(row = 5, column = 0, rowspan = 1, columnspan = 3, sticky = W+E+N+S)
for r in range(3):
self.Frame2.rowconfigure(r, weight=1)
for c in range(3):
self.Frame2.columnconfigure(c, weight = 1)
# Frame 3 #
self.Frame3 = Frame(self)
self.Frame3.grid(row = 5, column = 3, rowspan = 1, columnspan = 2, sticky = W+E+N+S)
self.Frame3.rowconfigure(0, weight = 1)
self.Frame3.columnconfigure(0, weight = 1)
# Propagation #
#self.grid_propagate(False) # All widgets (the 3 subframes) need to fit in Toplevel window. Minimal window size will be implemented later.
self.Canvas1.grid_propagate(False) # canvas works with scrollbar, widgets dont need to fit in window size.
#self.Frame1.grid_propagate(False) # Frame1 should resize to hold all data (label-widgets)
self.Frame2.grid_propagate(False) # fixed frame dimensions
self.Frame3.grid_propagate(False) # fixed textbox dimensions
self.Frame1.update_idletasks() # just to make sure
### Widgets for the multiple frames ###
# Frame1 - further populated by button command in frame 2#
self.lblaa = Label(self.Frame1, bg="white", text = "Processing...", justify = "left")
self.lblaa.grid(row = 0, column = 0, sticky = N+W)
self.LSlabelsr = []
self.LSlabelsa = []
self.LSlabelsb = []
# Frame 2 #
self.Wbuttontest=Button(self.Frame2, text="Start listing test", command = lambda: self.refresh())
self.Wbuttontest.grid(row = 0, column = 0, columnspan = 3)
self.Wentry = Entry(self.Frame2)
self.Wentry.grid(row = 2, column = 0, columnspan = 3, sticky = E+W, padx = 10)
self.Wentry.delete(0, END)
self.Wentry.insert(0, "user input here")
# Frame3 #
self.Wtext = Text(self.Frame3)
self.Wscrollb = Scrollbar(self.Frame3)
self.Wscrollb.config(command = self.Wtext.yview)
self.Wtext.config(yscrollcommand = self.Wscrollb.set)
self.Wtext.grid(row = 0, column = 0, sticky = N+E+W+S)
### Test-Lists ### Last character in the left column is "ez" !! ###
self.LSa = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
self.LSb = [1, 2, 3, 4, 66, 6, 7, 8, 9, 67, 11, 12, 13, 14, 68]
self.LSr = []
ib = 0
prefix = ""
for i in range(104):
if ib > 25:
prefix = chr(ord("a") + (i/ib - 1))
ib = 0
else:
pass
self.LSr.append(prefix + chr(97+ib))
ib += 1
### FUNCTIONS ###
def resize_frame(self, e):
self.Canvas1.itemconfig(self.CFrame1, width = e.width) #height of frame should depend on the contents.
def scrollevent(self, event):
self.Canvas1.configure(scrollregion=self.Canvas1.bbox("all"),width=200,height=200)
def refresh(self): ### Button-command: data will be shown ###
if self.lblaa.winfo_exists() == 1:
self.lblaa.destroy()
for i in range(len(self.LSr)):
self.Frame1.rowconfigure(i, weight = 0)
del self.LSlabelsr[:] # remove any previous labels from if the callback was called before
del self.LSlabelsa[:] # remove any previous labels from if the callback was called before
del self.LSlabelsb[:] # remove any previous labels from if the callback was called before
Vlabelheight = 1
# Left List #
for i in range(len(self.LSr)):
self.LSlabelsr.append(Label(self.Frame1, text = str(self.LSr[i]), bg = "LightBlue", justify = "left", height = Vlabelheight))
self.LSlabelsr[i].grid(row = i, column = 0, sticky = E+W)
# Middle List #
for i in range(len(self.LSa)):
self.LSlabelsa.append(Label(self.Frame1, text = str(self.LSa[i]), bg = "LightBlue", fg = "DarkViolet", justify = "left", height = Vlabelheight))
self.LSlabelsa[i].grid(row = i, column = 2, sticky = E+W)
# Right List #
for i in range(len(self.LSb)):
self.LSlabelsb.append(Label(self.Frame1, text = str(self.LSb[i]), bg = "LightBlue", fg = "DarkGreen", justify = "left", height = Vlabelheight))
self.LSlabelsb[i].grid(row = i, column = 4, sticky = E+W)
self.Frame1.update()
self.Frame1.update_idletasks()
print("done")
if __name__ == "__main__":
root = Tk()
root.title("Invisible")
root.resizable(FALSE,FALSE)
root.withdraw()
app = Processing(root)
root.mainloop()
要么是你的缩进有误,要么是你的总体错误。
您的所有函数都在您的 __init__
函数中定义
其次:如果你想调用一个class函数,你通过obj.function
调用它
您在 lambda: resize(self)
上的错误可能会发生,因为它应该是 lambda: self.resize
。
用这个试试吧。
并且请确保您的 缩进 是正确的。
我完全同意 Bryan 的观点——省略 lambda 表达式(我个人的观点)更易于阅读,并且 "better" 具有更结构化和实用的编码风格。
此脚本在 运行 时打开一个 window,分为 3 个框架:
- 将在其中显示数据的大框架(标签小部件)。
- 下方有一个较小的框架,带有用户输入小部件。
- 右下角带有文本框小部件的小框架。
大框架将包含大量数据(= 标签小部件),因此我需要它可滚动(垂直)。 这是我通过在滚动条小部件旁边创建一个 canvas 小部件来完成的。在canvas中放置了一个框架小部件。
似乎一切正常,但我的调整大小功能不起作用。 我的框架小部件没有更新其尺寸!这可能是因为我无法修复的错误。
基本问题:
脚本在第 43 行的“lambda: resize_frame(self)”命令中出错。我该如何解决这个问题?
旁注: 我的问题可能更多地与 canvas 小部件上的不正确绑定有关。因为我不确定我是否想要提供足够的上下文(脚本)。
非常感谢。
from Tkinter import *
import math
class Processing(Toplevel):
def __init__(self, master, *args, **kwargs):
Toplevel.__init__(self, master)
self.master = master
self.title("Process Window")
for r in range(6):
self.rowconfigure(r, weight = 1)
for c in range(4):
self.columnconfigure(c, weight = 1)
### WINDOW size and position definitions ###
ScreenSizeX = master.winfo_screenwidth()
ScreenSizeY = ( master.winfo_screenheight() - 75 ) #about 75pixels for taskbar on bottom of screen (Windows)
ScreenRatio = 0.9
FrameSizeX = int(ScreenSizeX * ScreenRatio)
FrameSizeY = int(ScreenSizeY * ScreenRatio)
FramePosX = (ScreenSizeX - FrameSizeX)/2
FramePosY = (ScreenSizeY - FrameSizeY)/2
self.geometry("%sx%s+%s+%s"%(FrameSizeX,FrameSizeY,FramePosX,FramePosY))
### Creating 3 "sub-frames" ###
# Frame 1 - canvas container with scrollbar#
self.Canvas1 = Canvas(self, bg = "white")
self.Canvas1.grid(row = 0, column = 0, rowspan = 5, columnspan = 4, sticky = N+E+S+W)
self.Canvas1.rowconfigure(1, weight = 1)
self.Canvas1.columnconfigure(1, weight = 1)
self.myscrollbar=Scrollbar(self, orient = "vertical", command = self.Canvas1.yview)
self.Canvas1.configure(yscrollcommand = self.myscrollbar.set)
self.myscrollbar.grid(row = 0, column = 4, rowspan = 5, sticky = N+S)
# Frame 1 - Frame widget in canvas #
self.Frame1 = Frame(self.Canvas1, bg = "white")
self.Frame1.rowconfigure(0, weight = 1)
for c in range(2):
self.Frame1.columnconfigure(1 + (2 * c), weight = 1)#1,3 - columns for small icons in the future
for cb in range(3):
self.Frame1.columnconfigure((cb * 2), weight = 9)#0,2,4 - columns for data
self.CFrame1 = self.Canvas1.create_window(0, 0, window = self.Frame1, width = FrameSizeX, anchor = N+W)
self.Canvas1.bind("<Configure>", lambda: resize_frame(self)) # !!!!! Doesn't work & gives error !!!!!! #
self.Frame1.bind("<Configure>", lambda: scrollevent(self))
self.Canvas1.config(scrollregion=self.Canvas1.bbox("all"))
# Frame 2 #
self.Frame2 = Frame(self, bg= "yellow")
self.Frame2.grid(row = 5, column = 0, rowspan = 1, columnspan = 3, sticky = W+E+N+S)
for r in range(3):
self.Frame2.rowconfigure(r, weight=1)
for c in range(3):
self.Frame2.columnconfigure(c, weight = 1)
# Frame 3 #
self.Frame3 = Frame(self)
self.Frame3.grid(row = 5, column = 3, rowspan = 1, columnspan = 2, sticky = W+E+N+S)
self.Frame3.rowconfigure(0, weight = 1)
self.Frame3.columnconfigure(0, weight = 1)
# Propagation #
#self.grid_propagate(False) # All widgets (the 3 subframes) need to fit in Toplevel window. Minimal window size will be implemented later.
self.Canvas1.grid_propagate(False) # canvas works with scrollbar, widgets dont need to fit in window size.
#self.Frame1.grid_propagate(False) # Frame1 should resize to hold all data (label-widgets)
self.Frame2.grid_propagate(False) # fixed frame dimensions
self.Frame3.grid_propagate(False) # fixed textbox dimensions
self.Frame1.update_idletasks() # just to make sure
### Widgets for the multiple frames ###
# Frame1 - further populated by button command in frame 2#
self.lblaa = Label(self.Frame1, bg="white", text = "Processing...", justify = "left")
self.lblaa.grid(row = 0, column = 0, sticky = N+W)
self.LSlabelsr = []
self.LSlabelsa = []
self.LSlabelsb = []
# Frame 2 #
self.Wbuttontest=Button(self.Frame2, text="Start listing test", command = lambda: refresh(self))
self.Wbuttontest.grid(row = 0, column = 0, columnspan = 3)
self.Wentry = Entry(self.Frame2)
self.Wentry.grid(row = 2, column = 0, columnspan = 3, sticky = E+W, padx = 10)
self.Wentry.delete(0, END)
self.Wentry.insert(0, "user input here")
# Frame3 #
self.Wtext = Text(self.Frame3)
self.Wscrollb = Scrollbar(self.Frame3)
self.Wscrollb.config(command = self.Wtext.yview)
self.Wtext.config(yscrollcommand = self.Wscrollb.set)
self.Wtext.grid(row = 0, column = 0, sticky = N+E+W+S)
### Test-Lists ### Last character in the left column is "ez" !! ###
self.LSa = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
self.LSb = [1, 2, 3, 4, 66, 6, 7, 8, 9, 67, 11, 12, 13, 14, 68]
self.LSr = []
ib = 0
prefix = ""
for i in range(104):
if ib > 25:
prefix = chr(ord("a") + (i/ib - 1))
ib = 0
else:
pass
self.LSr.append(prefix + chr(97+ib))
ib += 1
### FUNCTIONS ###
def resize_frame(self, event):
self.Canvas1.itemconfig(self.CFrame1, width = e.width) #height of frame should depend on the contents.
def scrollevent(event):
self.Canvas1.configure(scrollregion=self.Canvas1.bbox("all"),width=200,height=200)
def refresh(self): ### Button-command: data will be shown ###
if self.lblaa.winfo_exists() == 1:
self.lblaa.destroy()
for i in range(len(self.LSr)):
self.Frame1.rowconfigure(i, weight = 0)
del self.LSlabelsr[:] # remove any previous labels from if the callback was called before
del self.LSlabelsa[:] # remove any previous labels from if the callback was called before
del self.LSlabelsb[:] # remove any previous labels from if the callback was called before
Vlabelheight = 1
# Left List #
for i in range(len(self.LSr)):
self.LSlabelsr.append(Label(self.Frame1, text = str(self.LSr[i]), bg = "LightBlue", justify = "left", height = Vlabelheight))
self.LSlabelsr[i].grid(row = i, column = 0, sticky = E+W)
# Middle List #
for i in range(len(self.LSa)):
self.LSlabelsa.append(Label(self.Frame1, text = str(self.LSa[i]), bg = "LightBlue", fg = "DarkViolet", justify = "left", height = Vlabelheight))
self.LSlabelsa[i].grid(row = i, column = 2, sticky = E+W)
# Right List #
for i in range(len(self.LSb)):
self.LSlabelsb.append(Label(self.Frame1, text = str(self.LSb[i]), bg = "LightBlue", fg = "DarkGreen", justify = "left", height = Vlabelheight))
self.LSlabelsb[i].grid(row = i, column = 4, sticky = E+W)
self.Frame1.update()
self.Frame1.update_idletasks()
print("done")
if __name__ == "__main__":
root = Tk()
root.title("Invisible")
root.resizable(FALSE,FALSE)
root.withdraw()
app = Processing(root)
root.mainloop()
R4PH4EL 建议后的工作版本:
- 正确缩进:函数被定义为 init 的一部分。
对第 43/107 和 44/110 行的 lambda 命令进行了一些调整。
from Tkinter import * import math class Processing(Toplevel): def __init__(self, master, *args, **kwargs): Toplevel.__init__(self, master) self.master = master self.title("Process Window") for r in range(6): self.rowconfigure(r, weight = 1) for c in range(4): self.columnconfigure(c, weight = 1) ### WINDOW size and position definitions ### ScreenSizeX = master.winfo_screenwidth() ScreenSizeY = ( master.winfo_screenheight() - 75 ) #about 75pixels for taskbar on bottom of screen (Windows) ScreenRatio = 0.9 FrameSizeX = int(ScreenSizeX * ScreenRatio) FrameSizeY = int(ScreenSizeY * ScreenRatio) FramePosX = (ScreenSizeX - FrameSizeX)/2 FramePosY = (ScreenSizeY - FrameSizeY)/2 self.geometry("%sx%s+%s+%s"%(FrameSizeX,FrameSizeY,FramePosX,FramePosY)) ### Creating 3 "sub-frames" ### # Frame 1 - canvas container with scrollbar# self.Canvas1 = Canvas(self, bg = "white") self.Canvas1.grid(row = 0, column = 0, rowspan = 5, columnspan = 4, sticky = N+E+S+W) self.Canvas1.rowconfigure(1, weight = 1) self.Canvas1.columnconfigure(1, weight = 1) self.myscrollbar=Scrollbar(self, orient = "vertical", command = self.Canvas1.yview) self.Canvas1.configure(yscrollcommand = self.myscrollbar.set) self.myscrollbar.grid(row = 0, column = 4, rowspan = 5, sticky = N+S) # Frame 1 - Frame widget in canvas # self.Frame1 = Frame(self.Canvas1, bg = "white") self.Frame1.rowconfigure(0, weight = 1) for c in range(2): self.Frame1.columnconfigure(1 + (2 * c), weight = 1)#1,3 - columns for small icons in the future for cb in range(3): self.Frame1.columnconfigure((cb * 2), weight = 9)#0,2,4 - columns for data self.CFrame1 = self.Canvas1.create_window(0, 0, window = self.Frame1, width = FrameSizeX, anchor = N+W) self.Canvas1.bind("<Configure>", lambda event: self.resize_frame(event)) # !!!!! Doesn't work & gives error !!!!!! # self.Frame1.bind("<Configure>", lambda event: self.scrollevent(event)) self.Canvas1.config(scrollregion=self.Canvas1.bbox("all")) # Frame 2 # self.Frame2 = Frame(self, bg= "yellow") self.Frame2.grid(row = 5, column = 0, rowspan = 1, columnspan = 3, sticky = W+E+N+S) for r in range(3): self.Frame2.rowconfigure(r, weight=1) for c in range(3): self.Frame2.columnconfigure(c, weight = 1) # Frame 3 # self.Frame3 = Frame(self) self.Frame3.grid(row = 5, column = 3, rowspan = 1, columnspan = 2, sticky = W+E+N+S) self.Frame3.rowconfigure(0, weight = 1) self.Frame3.columnconfigure(0, weight = 1) # Propagation # #self.grid_propagate(False) # All widgets (the 3 subframes) need to fit in Toplevel window. Minimal window size will be implemented later. self.Canvas1.grid_propagate(False) # canvas works with scrollbar, widgets dont need to fit in window size. #self.Frame1.grid_propagate(False) # Frame1 should resize to hold all data (label-widgets) self.Frame2.grid_propagate(False) # fixed frame dimensions self.Frame3.grid_propagate(False) # fixed textbox dimensions self.Frame1.update_idletasks() # just to make sure ### Widgets for the multiple frames ### # Frame1 - further populated by button command in frame 2# self.lblaa = Label(self.Frame1, bg="white", text = "Processing...", justify = "left") self.lblaa.grid(row = 0, column = 0, sticky = N+W) self.LSlabelsr = [] self.LSlabelsa = [] self.LSlabelsb = [] # Frame 2 # self.Wbuttontest=Button(self.Frame2, text="Start listing test", command = lambda: self.refresh()) self.Wbuttontest.grid(row = 0, column = 0, columnspan = 3) self.Wentry = Entry(self.Frame2) self.Wentry.grid(row = 2, column = 0, columnspan = 3, sticky = E+W, padx = 10) self.Wentry.delete(0, END) self.Wentry.insert(0, "user input here") # Frame3 # self.Wtext = Text(self.Frame3) self.Wscrollb = Scrollbar(self.Frame3) self.Wscrollb.config(command = self.Wtext.yview) self.Wtext.config(yscrollcommand = self.Wscrollb.set) self.Wtext.grid(row = 0, column = 0, sticky = N+E+W+S) ### Test-Lists ### Last character in the left column is "ez" !! ### self.LSa = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] self.LSb = [1, 2, 3, 4, 66, 6, 7, 8, 9, 67, 11, 12, 13, 14, 68] self.LSr = [] ib = 0 prefix = "" for i in range(104): if ib > 25: prefix = chr(ord("a") + (i/ib - 1)) ib = 0 else: pass self.LSr.append(prefix + chr(97+ib)) ib += 1 ### FUNCTIONS ### def resize_frame(self, e): self.Canvas1.itemconfig(self.CFrame1, width = e.width) #height of frame should depend on the contents. def scrollevent(self, event): self.Canvas1.configure(scrollregion=self.Canvas1.bbox("all"),width=200,height=200) def refresh(self): ### Button-command: data will be shown ### if self.lblaa.winfo_exists() == 1: self.lblaa.destroy() for i in range(len(self.LSr)): self.Frame1.rowconfigure(i, weight = 0) del self.LSlabelsr[:] # remove any previous labels from if the callback was called before del self.LSlabelsa[:] # remove any previous labels from if the callback was called before del self.LSlabelsb[:] # remove any previous labels from if the callback was called before Vlabelheight = 1 # Left List # for i in range(len(self.LSr)): self.LSlabelsr.append(Label(self.Frame1, text = str(self.LSr[i]), bg = "LightBlue", justify = "left", height = Vlabelheight)) self.LSlabelsr[i].grid(row = i, column = 0, sticky = E+W) # Middle List # for i in range(len(self.LSa)): self.LSlabelsa.append(Label(self.Frame1, text = str(self.LSa[i]), bg = "LightBlue", fg = "DarkViolet", justify = "left", height = Vlabelheight)) self.LSlabelsa[i].grid(row = i, column = 2, sticky = E+W) # Right List # for i in range(len(self.LSb)): self.LSlabelsb.append(Label(self.Frame1, text = str(self.LSb[i]), bg = "LightBlue", fg = "DarkGreen", justify = "left", height = Vlabelheight)) self.LSlabelsb[i].grid(row = i, column = 4, sticky = E+W) self.Frame1.update() self.Frame1.update_idletasks() print("done") if __name__ == "__main__": root = Tk() root.title("Invisible") root.resizable(FALSE,FALSE) root.withdraw() app = Processing(root) root.mainloop()
要么是你的缩进有误,要么是你的总体错误。
您的所有函数都在您的 __init__
函数中定义
其次:如果你想调用一个class函数,你通过obj.function
您在 lambda: resize(self)
上的错误可能会发生,因为它应该是 lambda: self.resize
。
用这个试试吧。 并且请确保您的 缩进 是正确的。
我完全同意 Bryan 的观点——省略 lambda 表达式(我个人的观点)更易于阅读,并且 "better" 具有更结构化和实用的编码风格。