Python 关闭顶层窗口后在主窗口中滚动时出错
我正在使用Tkinter构建应用程序,我需要可滚动的窗口。我使用画布创建了一个可滚动的容器:ScrollContainer。在此之后,我将程序的主要逻辑合并到这个容器中,在其中我放置了一个按钮,打开另一个单独的顶级窗口。这个单独的窗口也必须是可滚动的。因此,我还将其包含在同一容器类中 现在,问题是:当我运行程序时,我的主窗口滚动良好。单击按钮后,我打开顶层窗口。辅助窗口滚动良好。在我关闭辅助窗口并将鼠标再次悬停在主窗口上后,现在它不会滚动,并且控制台中出现错误:Python 关闭顶层窗口后在主窗口中滚动时出错,python,tkinter,tkinter-canvas,Python,Tkinter,Tkinter Canvas,我正在使用Tkinter构建应用程序,我需要可滚动的窗口。我使用画布创建了一个可滚动的容器:ScrollContainer。在此之后,我将程序的主要逻辑合并到这个容器中,在其中我放置了一个按钮,打开另一个单独的顶级窗口。这个单独的窗口也必须是可滚动的。因此,我还将其包含在同一容器类中 现在,问题是:当我运行程序时,我的主窗口滚动良好。单击按钮后,我打开顶层窗口。辅助窗口滚动良好。在我关闭辅助窗口并将鼠标再次悬停在主窗口上后,现在它不会滚动,并且控制台中出现错误: Exception in Tki
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\mirel.voicu\Anaconda3\envs\gis385\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "C:/Users/mirel.voicu/Desktop/python_projects/TKINTER/standalone_program/test.py", line 45, in _on_mousewheel
self.my_canvas.yview_scroll(int(-1*(event.delta/120)), "units")
File "C:\Users\mirel.voicu\Anaconda3\envs\gis385\lib\tkinter\__init__.py", line 1929, in yview_scroll
self.tk.call(self._w, 'yview', 'scroll', number, what)
_tkinter.TclError: invalid command name ".!toplevel.!frame.!canvas"
注意:
我也尝试了使用self.my\u canvas.bind(“,self.\u在鼠标滚轮上)
而不是self.my\u canvas.bind(“,self.\u在鼠标滚轮上)
,现在没有错误。但是,滚动改变了。如果将鼠标悬停在标签上,则无法再滚动。只有将窗口放大并将鼠标悬停在右侧一点,才能滚动。我猜这是因为你必须把鼠标放在画布上,因为它是唯一可以滚动的实体
ScrollContainer类别:
from tkinter import *
from tkinter import ttk
class ScrollContainer (ttk.Frame):
def __init__(self, container,w,h,*args, **kwargs):
super().__init__(container, *args, **kwargs)
# Create a main frame
self.main_frame = Frame(container, width=w, height=h)
self.main_frame.pack(side=TOP,fill=BOTH, expand=1) # expand frame to the size of the container
# create a canvas
self.my_canvas = Canvas(self.main_frame)
self.my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
self.my_canvas.bind_all("<MouseWheel>", self._on_mousewheel)
# add h and v scrollbar to canvas
self.my_vscrollbar = ttk.Scrollbar(self.main_frame, orient=VERTICAL, command=self.my_canvas.yview)
self.my_vscrollbar.pack(side=RIGHT, fill=Y)
self.my_hscrollbar = ttk.Scrollbar(container, orient=HORIZONTAL, command=self.my_canvas.xview)
self.my_hscrollbar.pack(side=BOTTOM, fill=X)
# configure canvas
self.my_canvas.configure(yscrollcommand=self.my_vscrollbar.set, xscrollcommand=self.my_hscrollbar.set)
self.my_canvas.bind('<Configure>', lambda e: self.my_canvas.configure(scrollregion=self.my_canvas.bbox('all')))
# create another frame inside the canvas
self.second_frame = Frame(self.my_canvas)
# add that new frame to a window in the canvas
self.my_canvas.create_window((0, 0), window=self.second_frame, anchor='nw')
def _on_mousewheel(self, event):
self.my_canvas.yview_scroll(int(-1*(event.delta/120)), "units")
这是因为您使用了
bind\u all()
,这是一种基于应用程序的绑定。因此,Toplevel()
中的绑定将覆盖根目录中的绑定。当toplevel被销毁时,绑定函数仍在引用toplevel中的画布,因此出现异常
您应该使用窗口绑定:
类滚动容器(ttk.Frame):
定义初始化(self,container,w,h,*args,**kwargs):
super()
container.bind(“,self._在鼠标滚轮上)#在父窗口上绑定
#创建一个主框架
self.main_frame=frame(容器,宽度=w,高度=h)
self.main_frame.pack(side=TOP,fill=BOTH,expand=1)#将框架扩展到容器的大小
#创建画布
self.my_canvas=画布(self.main_框架)
self.my_canvas.pack(side=LEFT,fill=BOTH,expand=1)
#self.my\u canvas.bind\u all(“,self.\u在鼠标滚轮上)
#将h和v滚动条添加到画布
self.my\u vscrollbar=ttk.Scrollbar(self.main\u frame,orient=VERTICAL,command=self.my\u canvas.yview)
self.my_vscrollbar.pack(side=RIGHT,fill=Y)
self.my\hscrollbar=ttk.Scrollbar(容器,方向=水平,命令=self.my\u canvas.xview)
self.my\hscrollbar.pack(侧面=底部,填充=X)
#配置画布
self.my_canvas.configure(yscrollcommand=self.my_vscrollbar.set,xscrollcommand=self.my_hscrollbar.set)
self.my\u canvas.bind(“”,lambda e:self.my\u canvas.configure(scrollregion=self.my\u canvas.bbox('all'))
#在画布内创建另一个框架
self.second\u frame=frame(self.my\u画布)
#将新框架添加到画布中的窗口
self.my\u canvas.create\u window((0,0),window=self.second\u frame,anchor='nw')
鼠标滚轮上的def(自身、事件):
self.my_canvas.yview_滚动条(int(-1*(event.delta/120)),“单位”)
这是因为您使用了bind\u all()
,这是一种基于应用程序的绑定。因此,Toplevel()
中的绑定将覆盖根目录中的绑定。当toplevel被销毁时,绑定函数仍在引用toplevel中的画布,因此出现异常
您应该使用窗口绑定:
类滚动容器(ttk.Frame):
定义初始化(self,container,w,h,*args,**kwargs):
super()
container.bind(“,self._在鼠标滚轮上)#在父窗口上绑定
#创建一个主框架
self.main_frame=frame(容器,宽度=w,高度=h)
self.main_frame.pack(side=TOP,fill=BOTH,expand=1)#将框架扩展到容器的大小
#创建画布
self.my_canvas=画布(self.main_框架)
self.my_canvas.pack(side=LEFT,fill=BOTH,expand=1)
#self.my\u canvas.bind\u all(“,self.\u在鼠标滚轮上)
#将h和v滚动条添加到画布
self.my\u vscrollbar=ttk.Scrollbar(self.main\u frame,orient=VERTICAL,command=self.my\u canvas.yview)
self.my_vscrollbar.pack(side=RIGHT,fill=Y)
self.my\hscrollbar=ttk.Scrollbar(容器,方向=水平,命令=self.my\u canvas.xview)
self.my\hscrollbar.pack(侧面=底部,填充=X)
#配置画布
self.my_canvas.configure(yscrollcommand=self.my_vscrollbar.set,xscrollcommand=self.my_hscrollbar.set)
self.my\u canvas.bind(“”,lambda e:self.my\u canvas.configure(scrollregion=self.my\u canvas.bbox('all'))
#在画布内创建另一个框架
self.second\u frame=frame(self.my\u画布)
#将新框架添加到画布中的窗口
self.my\u canvas.create\u window((0,0),window=self.second\u frame,anchor='nw')
鼠标滚轮上的def(自身、事件):
self.my_canvas.yview_滚动条(int(-1*(event.delta/120)),“单位”)
很酷。它起作用了。非常感谢您的回复。它起作用了。非常感谢您的回复
def open():
w=Toplevel()
SecondContainer=ScrollContainer(w,1000,768)
for thing in range(40):
Label(SecondContainer.second_frame, text=f"It's Friday {thing} ").grid(row=thing, column=0)
root=Tk()
MainContainer=ScrollContainer(root,1000,768)
btn=Button(MainContainer.second_frame, text="New Window",bg='yellow',command=open)
btn.grid(row=0,column=0)
for thing in range(1,30):
Label(MainContainer.second_frame,text=f"It's Friday {thing} ").grid(row=thing,column=0)
# frame design
root.mainloop()