【问题标题】:Tkinter 'bind' with 'canvas' and threading ValueErrorTkinter 'bind' 与 'canvas' 和线程 ValueError
【发布时间】:2014-07-03 18:41:43
【问题描述】:

起初,我认为这是一个可以在我发现的this 帖子中解决的问题。但是,我尝试实现 after 方法,但它似乎不起作用。 (关于我如何相信我的问题是不同的并且不是重复的更多信息在下面稍远一点。)

在尝试将button-1 绑定到函数callback 时形成错误,该函数从与其他线程不同的线程运行。有问题的代码在这里

def callback(event):
    print(event)  #This function normally changes playerY, however it prints the event for debugging purpose.

def drawPlayer():
    global playerY, playerY2
    player = canvas.create_oval(50,50,100,100,fill="yellow",outline="black")
    while True:
        canvas.coords(player,(50,50,100,100))  #This would usually use playerY and playerY2 but for debugging it does not.
        playerY += 0.0018
        playerY2 += 0.0018

root.bind("<Button-1>",callback)
thread2 = Thread(target=drawPlayer)
thread2.start()

显然,root、playerY、playerY2 等内容已经定义,但我不打算粘贴我的整个代码。

单击按钮 1 时,将产生以下回溯

Exception in thread Thread-2:
Traceback (most recent call last):
  File "C:\Python33\lib\threading.py", line 637, in _bootstrap_inner
    self.run()
  File "C:\Python33\lib\threading.py", line 594, in run
     self._target(*self._args, **self._kwargs)
  File "C:\Users\Harvey\Documents\School Work\Computer    Science\Tkinter\tkinterFallpyBird.py", line 58, in drawPlayer
    canvas.coords(player,(50,50,100,100))
  File "C:\Python33\lib\tkinter\__init__.py", line 2299, in coords
     self.tk.call((self._w, 'coords') + args))]
  File "C:\Python33\lib\tkinter\__init__.py", line 2297, in <listcomp>
    return [getdouble(x) for x in
ValueError: could not convert string to float: 'None'

另一个线程告诉我使用 'after' 方法来解决这个问题。为此,我尝试了:

def drawPlayer():
    global playerY, playerY2,player
    canvas.coords(player,(playerY,50,playerY2,100))
    playerY += 0.0018
    playerY2 += 0.0018

    root.after(1,drawPlayer)

root.bind("<Button-1>",callback)

player = canvas.create_oval(50,50,100,100,fill="yellow",outline="black")
drawPlayer()

root.mainloop()

我的函数drawPlayer 需要重复调​​用,因此线程版本中的while 循环。我觉得这就是我的问题与我一开始联系的问题的不同之处。我尝试在root.after() 调用中使用0,但这只会导致调用drawPlayer() 之后的代码没有运行。

除非我缺少与 after 方法或线程模块有关的内容,否则我不明白如何解决此问题。


旁注:我意识到我不应该在 tkinter 中制作游戏,尤其是需要同时发生多件事的游戏。但是,我在学校这样做,并且我想使用的模块(Pygame 或 Pyglet)不能仅仅为了我制作一个没有真正目的的游戏而下载。如果我可以使用 tkinter 以外的东西,我可能会。谢谢您的帮助。

【问题讨论】:

  • after() 的版本你得到了什么结果?您是否尝试过具有更大价值的after()?例如10 ?使用1(一毫秒),您可以获得 1000 FPS(每秒帧数),但您不需要它。
  • @furas 我尝试了 10、20、50 和 100。这些都没有做任何事情。正在调用该函数,但即使在我更改为使用 playerY 和 playerY2 之后坐标也没有改变

标签: python multithreading canvas tkinter


【解决方案1】:

尝试after 版本,但在playerYplayerY2 中添加比0.0018 更多的内容。

至少试试1

工作示例:

from Tkinter import *

root = Tk()

canvas = Canvas(root)
canvas.pack()

playerY = 50
playerY2 = 100

def drawPlayer():
    global playerY, playerY2,player
    canvas.coords(player,(playerY,50,playerY2,100))
    playerY += 1
    playerY2 += 1
    root.after(10,drawPlayer)

#root.bind("<Button-1>",callback)

player = canvas.create_oval(50,50,100,100,fill="yellow",outline="black")
drawPlayer()

root.mainloop()

【讨论】:

  • 感谢您的回复。可悲的是,我还不能尝试这个,但这不能满足我的需要。值这么小的原因是因为我需要椭圆形以合理的速度慢慢下降。如果为 1,则会太快从屏幕上掉下来。
  • 然后在after()中使用更大的值。例如,将10 更改为100,您的移动速度会慢 10 倍。它为您提供与添加0.1 代替1 相同的结果,但您将使用更少的CPU 功率并且它将在每台计算机上以相同的速度运行 - 使用after() 动画速度取决于时间,而不是CPU 速度。您可以轻松添加另一个 after() 来制作另一个动画元素。
  • 感谢您的帮助。我认为这会奏效,尽管我要到明天晚上晚些时候才能尝试!
猜你喜欢
  • 2020-08-17
  • 1970-01-01
  • 1970-01-01
  • 2014-12-29
  • 2014-07-30
  • 2013-10-14
  • 1970-01-01
相关资源
最近更新 更多