简体   繁体   English

与Tkinter的多线程python

[英]Mutli-threading python with Tkinter

I'm drawing little circles on a canvas with these functions : 我在画布上用这些函数绘制小圆圈:

This is the function that will draw the circles : 这是绘制圆圈的功能:

class Fourmis:

def __init__(self, can, posx, posy, name, radius):
    self.can = can

    self.largeur_can = int(self.can.cget("width"))
    self.hauteur_can = int(self.can.cget("height"))

    self.posx = posx
    self.posy = posy
    self.name = name 
    self.radius = radius

    self.ball1 = self.can.create_oval(self.posy, self.posx, self.posy+radius, self.posx+radius, outline=self.name, fill=self.name, width=2)

    self.nx = randrange(-10,10,1)
    self.nx /= 2.0
    self.ny = randrange(-10,10,1)
    self.ny /= 2.0

    #self.can.bind("<Motion>", self.destruction, add="+") 
    self.statut = True

    self.move()

def move(self):
    if self.statut == True :
        self.pos_ball = self.can.coords(self.ball1)
        self.posx_ball = self.pos_ball[0]
        self.posy_ball = self.pos_ball[1]

        if self.posx_ball < 0 or (self.posx_ball + self.radius) > self.largeur_can:
            self.nx = -self.nx         
        if self.posy_ball < 0 or (self.posy_ball + self.radius) > self.hauteur_can:
            self.ny = -self.ny

        self.can.move(self.ball1, self.nx, self.ny)

        self.can.after(10, self.move)

this one creates the canvas and the circles : 这个创建画布和圆圈:

class App(Frame):

def __init__(self):
    self.root=Tk()
    self.can=Canvas(self.root,width=800,height=600,bg="black")
    self.can.pack()

    self.create(50, "green")
    self.create(50, "purple")



def mainloop(self):
    self.root.mainloop()


def create(self, i, name):
    for x in range(i):
        self.x=Fourmis(self.can,100,400, name,0)

I call these lines to run the project : 我将这些行称为运行项目:

jeu = App()
jeu.mainloop()

What is the correct way to execute self.create(50, "green") and self.create(50, "purple") in different threads? 在不同的线程中执行self.create(50, "green")self.create(50, "purple")的正确方法是什么?

I have tried the following, but could not get it to work.: 我尝试了以下,但无法让它工作:

class FuncThread(threading.Thread):
def __init__(self, i, name):
    self.i = i
    self.name = name
    threading.Thread.__init__(self)

def run(self):
    App.create(self, self.i, self.name)

Is someone able to tell me how to run these threads? 有人能告诉我如何运行这些线程吗?

When this functionality is needed, what you do is schedule the events you wish to perform by putting them in a queue shared by the threads. 当需要此功能时,您所做的是通过将它们放入由线程共享的队列中来安排您希望执行的事件。 This way, in a given thread you specify that you want to run "create(50, ...)" by queueing it, and the main thread dequeue the event and perform it. 这样,在给定的线程中,您通过对其进行排队来指定要运行“create(50,...)”,并且主线程将事件排队并执行它。

Here is a basic example for creating moving balls in a second thread: 这是在第二个线程中创建移动球的基本示例:

import threading
import Queue
import random
import math
import time
import Tkinter

random.seed(0)

class App:
    def __init__(self, queue, width=400, height=300):
        self.width, self.height = width, height
        self.canvas = Tkinter.Canvas(width=width, height=height, bg='black')
        self.canvas.pack(fill='none', expand=False)
        self._oid = []
        self.canvas.after(10, self.move)

        self.queue = queue
        self.canvas.after(50, self.check_queue)

    def check_queue(self):
        try:
            x, y, rad, outline = self.queue.get(block=False)
        except Queue.Empty:
            pass
        else:
            self.create_moving_ball(x, y, rad, outline)
        self.canvas.after(50, self.check_queue)

    def move(self):
        width, height = self.width, self.height
        for i, (oid, r, angle, speed, (x, y)) in enumerate(self._oid):
            sx, sy = speed
            dx = sx * math.cos(angle)
            dy = sy * math.sin(angle)
            if y + dy + r> height or y + dy - r < 0:
                sy = -sy
                self._oid[i][3] = (sx, sy)
            if x + dx + r > width or x + dx - r < 0:
                sx = -sx
                self._oid[i][3] = (sx, sy)
            nx, ny = x + dx, y + dy
            self._oid[i][-1] = (nx, ny)
            self.canvas.move(oid, dx, dy)
        self.canvas.update_idletasks()
        self.canvas.after(10, self.move)

    def create_moving_ball(self, x=100, y=100, rad=20, outline='white'):
        oid = self.canvas.create_oval(x - rad, y - rad, x + rad, y + rad,
                outline=outline)
        oid_angle = math.radians(random.randint(1, 360))
        oid_speed = random.randint(2, 5)
        self._oid.append([oid, rad, oid_angle, (oid_speed, oid_speed), (x, y)])

def queue_create(queue, running):
    while running:
        if random.random() < 1e-6:
            print "Create a new moving ball please"
            x, y = random.randint(100, 150), random.randint(100, 150)
            color = random.choice(['green', 'white', 'yellow', 'blue'])
            queue.put((x, y, random.randint(10, 30), color))
        time.sleep(0) # Effectively yield this thread.

root = Tkinter.Tk()
running = [True]

queue = Queue.Queue()

app = App(queue)
app.create_moving_ball()
app.canvas.bind('<Destroy>', lambda x: (running.pop(), x.widget.destroy()))

thread = threading.Thread(target=queue_create, args=(queue, running))
thread.start()

root.mainloop()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM