python Tkinter 多线程
python Tkinter multithreading
我正在尝试让两个球在屏幕上移动位置正在用线程更新并且主线程正在更新图形这里是我的代码:
from tkinter import *
from threading import *
import time
width = 500
height = 500
class Ball(Thread):
def __init__(self, canvas, x1, y1, x2, y2, color):
super().__init__()
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
self.x_velocity = 9
self.y_velocity = 5
self.canvas = canvas
self.id = self.canvas.create_oval(self.x1, self.y1, self.x2, self.y2, fill=color)
def update(self):
self.canvas.move(self.id, self.x_velocity, self.y_velocity)
pos = self.canvas.coords(self.id)
if pos[0] <= 0 or pos[2] >= width:
self.x_velocity *= -1
if pos[1] <= 0 or pos[3] >= height:
self.y_velocity *= -1
def run(self):
self.update()
def main():
master = Tk()
canvas = Canvas(master=master, bg='Grey', width=width, height=height)
ball1 = Ball(canvas=canvas, x1=10, y1=10, x2=40, y2=40, color='Black')
ball2 = Ball(canvas=canvas, x1=50, y1=50, x2=80, y2=80, color='Red')
canvas.pack()
ball1.start()
ball2.start()
while 1:
master.update()
time.sleep(0.04)
if __name__ == '__main__':
main()
似乎不工作 出了什么问题以及如何处理?
错误信息是:
Exception in thread Thread-2: Traceback (most recent call last): File "/home/muhammad_essam/anaconda3/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run() File "/mnt/sda6/CSE/Project/GUI/Learnning/GUI101/main.py", line 30, in run
self.update() File "/mnt/sda6/CSE/Project/GUI/Learnning/GUI101/main.py", line 22, in update
self.canvas.move(self.id, self.x_velocity, self.y_velocity) File "/home/muhammad_essam/anaconda3/lib/python3.6/tkinter/__init__.py", line 2585, in move
self.tk.call((self._w, 'move') + args)
_tkinter.TclError: out of stack space (infinite loop?)
Exception in thread Thread-1: Traceback (most recent call last): File "/home/muhammad_essam/anaconda3/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run() File "/mnt/sda6/CSE/Project/GUI/Learnning/GUI101/main.py", line 30, in run
self.update() File "/mnt/sda6/CSE/Project/GUI/Learnning/GUI101/main.py", line 22, in update
self.canvas.move(self.id, self.x_velocity, self.y_velocity) File "/home/muhammad_essam/anaconda3/lib/python3.6/tkinter/__init__.py", line 2585, in move
self.tk.call((self._w, 'move') + args)
_tkinter.TclError: out of stack space (infinite loop?)
您的程序不难修改,因此它使用 GUI 主循环和 after
方法调用。 main
函数中的代码可能应该封装在继承自 tkinter.Frame
的 class 中,但以下示例已完成并演示了一种可能的解决方案:
#! /usr/bin/env python3
import tkinter
FPS = 25
WIDTH, HEIGHT = 500, 500
def main():
tkinter.NoDefaultRoot()
root = tkinter.Tk()
root.resizable(False, False)
canvas = tkinter.Canvas(root, bg='grey', width=WIDTH, height=HEIGHT)
canvas.grid()
balls = (
Ball(canvas, 10, 10, 40, 40, 'black'),
Ball(canvas, 50, 50, 80, 80, 'red')
)
root.after(1000 // FPS, update_balls, root, balls)
root.mainloop()
def update_balls(root, balls):
root.after(1000 // FPS, update_balls, root, balls)
for ball in balls:
ball.update()
class Ball:
def __init__(self, canvas, x1, y1, x2, y2, color):
self.__canvas = canvas
self.__x_velocity = 9
self.__y_velocity = 5
self.__id = canvas.create_oval(x1, y1, x2, y2, fill=color)
def update(self):
self.__canvas.move(self.__id, self.__x_velocity, self.__y_velocity)
x1, y1, x2, y2 = self.__canvas.coords(self.__id)
if x1 < 0 or x2 > WIDTH:
self.__x_velocity *= -1
if y1 < 0 or y2 > HEIGHT:
self.__y_velocity *= -1
if __name__ == '__main__':
main()
我正在尝试让两个球在屏幕上移动位置正在用线程更新并且主线程正在更新图形这里是我的代码:
from tkinter import *
from threading import *
import time
width = 500
height = 500
class Ball(Thread):
def __init__(self, canvas, x1, y1, x2, y2, color):
super().__init__()
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
self.x_velocity = 9
self.y_velocity = 5
self.canvas = canvas
self.id = self.canvas.create_oval(self.x1, self.y1, self.x2, self.y2, fill=color)
def update(self):
self.canvas.move(self.id, self.x_velocity, self.y_velocity)
pos = self.canvas.coords(self.id)
if pos[0] <= 0 or pos[2] >= width:
self.x_velocity *= -1
if pos[1] <= 0 or pos[3] >= height:
self.y_velocity *= -1
def run(self):
self.update()
def main():
master = Tk()
canvas = Canvas(master=master, bg='Grey', width=width, height=height)
ball1 = Ball(canvas=canvas, x1=10, y1=10, x2=40, y2=40, color='Black')
ball2 = Ball(canvas=canvas, x1=50, y1=50, x2=80, y2=80, color='Red')
canvas.pack()
ball1.start()
ball2.start()
while 1:
master.update()
time.sleep(0.04)
if __name__ == '__main__':
main()
似乎不工作 出了什么问题以及如何处理? 错误信息是:
Exception in thread Thread-2: Traceback (most recent call last): File "/home/muhammad_essam/anaconda3/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run() File "/mnt/sda6/CSE/Project/GUI/Learnning/GUI101/main.py", line 30, in run
self.update() File "/mnt/sda6/CSE/Project/GUI/Learnning/GUI101/main.py", line 22, in update
self.canvas.move(self.id, self.x_velocity, self.y_velocity) File "/home/muhammad_essam/anaconda3/lib/python3.6/tkinter/__init__.py", line 2585, in move
self.tk.call((self._w, 'move') + args)
_tkinter.TclError: out of stack space (infinite loop?)
Exception in thread Thread-1: Traceback (most recent call last): File "/home/muhammad_essam/anaconda3/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run() File "/mnt/sda6/CSE/Project/GUI/Learnning/GUI101/main.py", line 30, in run
self.update() File "/mnt/sda6/CSE/Project/GUI/Learnning/GUI101/main.py", line 22, in update
self.canvas.move(self.id, self.x_velocity, self.y_velocity) File "/home/muhammad_essam/anaconda3/lib/python3.6/tkinter/__init__.py", line 2585, in move
self.tk.call((self._w, 'move') + args)
_tkinter.TclError: out of stack space (infinite loop?)
您的程序不难修改,因此它使用 GUI 主循环和 after
方法调用。 main
函数中的代码可能应该封装在继承自 tkinter.Frame
的 class 中,但以下示例已完成并演示了一种可能的解决方案:
#! /usr/bin/env python3
import tkinter
FPS = 25
WIDTH, HEIGHT = 500, 500
def main():
tkinter.NoDefaultRoot()
root = tkinter.Tk()
root.resizable(False, False)
canvas = tkinter.Canvas(root, bg='grey', width=WIDTH, height=HEIGHT)
canvas.grid()
balls = (
Ball(canvas, 10, 10, 40, 40, 'black'),
Ball(canvas, 50, 50, 80, 80, 'red')
)
root.after(1000 // FPS, update_balls, root, balls)
root.mainloop()
def update_balls(root, balls):
root.after(1000 // FPS, update_balls, root, balls)
for ball in balls:
ball.update()
class Ball:
def __init__(self, canvas, x1, y1, x2, y2, color):
self.__canvas = canvas
self.__x_velocity = 9
self.__y_velocity = 5
self.__id = canvas.create_oval(x1, y1, x2, y2, fill=color)
def update(self):
self.__canvas.move(self.__id, self.__x_velocity, self.__y_velocity)
x1, y1, x2, y2 = self.__canvas.coords(self.__id)
if x1 < 0 or x2 > WIDTH:
self.__x_velocity *= -1
if y1 < 0 or y2 > HEIGHT:
self.__y_velocity *= -1
if __name__ == '__main__':
main()