Skip to main content
 首页 » 编程设计

python Tkinter 多线程

2024年09月07日31mate10pro

我试图让两个球在屏幕上移动,位置正在用线程更新,主线程正在更新图形这里是我的代码:

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 的类中,但以下示例是完整的,并演示了一种可能的解决方案:

#! /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()