我正在尝试为我的 tkinter 应用程序创建一个滑动菜单栏,但我遇到了一个问题,我怀疑是因为我没有正确锁定线程。虽然我已经涉足 Python 一段时间了,但我对 tkinter 和线程应用程序都比较陌生,我希望这里的某个人能够阐明我做错了什么。
我的代码如下:
class MenuBar():
def slide_out(self, event = None):
def helper():
while self.canvas.coords(self.bg)[0] > 100 and self.mouseIn:
self.canvas.move(self.bg, -5, 0)
sleep(0.01)
self.mouseIn = True
Thread(target = helper).start()
def slide_in(self, event):
self.mouseIn = False
self.canvas.coords(self.bg, 750, 0)
def __init__(self, canvas):
self.canvas = canvas
self.bgImg = ImageTk.PhotoImage(file = "Options Bar.png")
self.bg = canvas.create_image(750, 0, anchor = "nw", image = self.bgImg, tags = ("menubar", "menubarbackground"))
self.mouseIn = False
self.canvas.tag_bind("menubar", "<Enter>", self.slide_out)
self.canvas.tag_bind("menubar", "<Leave>", self.slide_in)
我在 Canvas 小部件中工作,因为它使样式化更简单。将鼠标悬停在菜单栏上时收到的错误如下:
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python33\lib\threading.py", line 639, in _bootstrap_inner
self.run()
File "C:\Python33\lib\threading.py", line 596, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\alex\Desktop\Python - VN Work\readingscreen.py", line 12, in helper
while self.canvas.coords(self.bg)[0] > 100 and self.mouseIn:
File "C:\Python33\lib\tkinter\__init__.py", line 2264, in coords
self.tk.call((self._w, 'coords') + args))]
File "C:\Python33\lib\tkinter\__init__.py", line 2262, in <listcomp>
return [getdouble(x) for x in
ValueError: could not convert string to float: 'None'
现在,当我在线程外调用它时,它提示的 canvas 方法起作用了。还值得一提的是,如果我在 self.canvas.coords 调用之前在辅助函数中引用 self.bg,则不会发生错误。然而,添加一些无用的引用似乎很难解决。我担心如果我现在不解决这个问题,以后只会加剧其他一些问题。
我假设我需要锁定我的线程以便让它毫无问题地引用 self.bg 是正确的,或者这里有什么我遗漏的?我尝试向 MenuBar 类添加一个锁,在辅助方法中获取并释放它,但无济于事。
有人知道吗?谢谢。
请您参考如下方法:
Tkinter 不是线程安全的。您不能从创建小部件的线程以外的任何线程调用小部件上的方法。添加锁定不会有帮助。
对于像滑入和滑出菜单这样简单的事情,您不需要线程。有几个利用事件循环使用 Tkinter 制作动画的示例。算法基本上是这样的:
def animate(...):
<move the widget one or two pixels>
<if the widget needs to move some more>:
self.canvas.after(100, animate)
它的作用很简单:它将您的小部件移动一到两个像素,检查它是否完全可见,如果不可见,它会重新安排自身在几毫秒后再次运行。您可以通过调整每次迭代移动的像素数以及每帧动画之间的毫秒数来调整动画的速度和平滑度。
