这是我的代码,我检查了有关滚动条与tkinter的其他几个问题,但仍然无法弄清楚为什么我的设备(画布内的框架中的按钮无法滚动)
滚动条和画布似乎得到了配置事件,并且滚动条和画布yview被正确调用,但内部框架没有滚动它。 我错过了什么吗?
import tkinter as tk
import tkinter.font as tkFont
from tkinter import StringVar
c20 = None
c16 = None
class DebugScrollbar(tk.Scrollbar):
def set(self, *args):
print ("SCROLLBAR SET", args)
tk.Scrollbar.set(self, *args)
class DebugCanvas(tk.Canvas):
def yview(self, *args):
print("Canvas yview" , args)
tk.Canvas.yview(self, *args)
class Application:
def __init__(self):
master = tk.Tk()
global c20, c16
c20 = tkFont.Font( family ='Helvetica', size = 20)
c18 = tkFont.Font( family ='Helvetica', size = 18)
c12 = tkFont.Font( family ='Helvetica', size = 12)
self.c16 = c16 = tkFont.Font( family ='Helvetica', size = 16)
self.myIp = tk.StringVar()
self.master = master
master.option_add('*Font', c18)
self.c20 = c20
self.c24 = tkFont.Font( family='Helvetica', size=24)
##self._geom='200x200+0+0'
##master.geometry("{0}x{1}+0+0".format( master.winfo_screenwidth()-pad, master.winfo_screenheight()-pad))
master.title("Safe Home")
#master.attributes("-fullscreen", True)
self.topBar = tk.Frame(master)
self.topBar.grid(columnspan=5, sticky=tk.N)
self.wifiStatus = tk.StringVar()
self.wifiStatus.set("WIFI1 %d" )
self.wifi = tk.Label(self.topBar, textvariable= self.wifiStatus, borderwidth=2, relief="ridge", height=4, width=8)
self.wifi.grid(sticky=tk.E, row=1, column = 0 , padx=3, pady=3)
self.mainFrame = tk.Frame(self.master, relief=tk.GROOVE, bd=1)
self.mainFrame.grid(row=2, column=0 , columnspan=5 , rowspan=3, padx=3, pady=3)
self.prepareDevices(self.mainFrame)
self.devices.pack( side= tk.LEFT, padx=3, pady=3 )
#self.greet_button["font"]=c20
self.close_button = tk.Button(master, text="Close", command=master.quit)
self.close_button.grid(columnspan=1, sticky=tk.SE, row=6, column=4 )
#self.close_button["font"]=c20
self.addDevices(self.devices)
def prepareDevices(self, insideFrame):
insideFrame.grid_rowconfigure(0, weight=1)
insideFrame.grid_columnconfigure(0, weight=1)
vscrollbar = DebugScrollbar( insideFrame, orient=tk.VERTICAL)
vscrollbar.grid(row=0, column=1, sticky=tk.N+tk.S)
self.canvas = canvas = DebugCanvas( insideFrame, background = "#D2D2D2",# bd=1, relief='solid', highlightthickness=1,
#scrollregion=(0, 0, 1000, 1000),
yscrollcommand=vscrollbar.set)
vscrollbar.config(command = canvas.yview)
canvas.config( yscrollcommand = vscrollbar.set )
canvas.config(width = 100, height = 280)
canvas.grid(row=0, column=0, sticky=tk.N+tk.S+tk.E+tk.W)
vscrollbar.config(command = canvas.yview)
canvas.config( yscrollcommand = vscrollbar.set )
# reset the view
#canvas.xview_moveto(0)
#canvas.yview_moveto(0)
# create a frame inside the canvas which will be scrolled with it
self.devices = interior = tk.Frame(canvas #, bd=2 , relief='groove'
)
interior_id = canvas.create_window(0, 0, window=interior, anchor=tk.NW)
def _configure_interior(event):
# update the scrollbars to match the size of the inner frame
print("Configure interior event: %s" % (event))
size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
sizeStr= "0 0 %s %s" % size
print(sizeStr)
canvas.config( scrollregion = (0,0, interior.winfo_reqwidth(), interior.winfo_reqheight()) )
print ("canvas adjust region")
if interior.winfo_reqwidth() != canvas.winfo_width():
# update the canvas's width to fit the inner frame
canvas.config(width=interior.winfo_reqwidth())
canvas.config(width= 180, height = 280)
interior.bind('<Configure>', _configure_interior)
def _configure_canvas(event):
##
print("Configure canvas %s" % (event))
if interior.winfo_reqwidth() != canvas.winfo_width():
# update the inner frame's width to fill the canvas
canvas.itemconfigure(interior_id, width=canvas.winfo_width())
print ("canvas adjust width")
canvas.bind('<Configure>', _configure_canvas)
# track changes to the canvas and frame width and sync them,
# also updating the scrollbar
def addDevices(self, deviceFrame):
for i in range(1 , 20):
d = Device("1D:1s:%d" % i)
l = DeviceLabel(deviceFrame, name="device %s" % i, macAddress=d.macAddress, mainWindow = self)
class Device():
def __init__(self, macAddress):
self.macAddress = macAddress
pass
class DeviceLabel( ):
def __init__(self, parent, name, mainWindow, macAddress = None, status=None):
global c16
self.text = tk.StringVar()
self.label= tk.Button( parent, textvariable = self.text, bd=1, relief="groove", height=3, width=15, command = lambda: mainWindow.deviceDetail(macAddress))
self.macAddress = macAddress
self.status = status
self.name = name
self.text.set(name)
self.label["font"] = c16
self.label.pack()
my_gui = Application()
my_gui.master.mainloop()
答案 0 :(得分:3)
内部Frame
(self.devices
)是Canvas
上的元素,不是外部框架的一部分,也不是任何其他窗口小部件/窗口,所以你不应该这样做
self.devices.pack(side=tk.LEFT, padx=3, pady=3)
删除此行,它将正常工作。