如何在Python / Tkinter程序中停止其他进程或完成进程

时间:2014-06-20 23:28:35

标签: python tkinter

我一直在用Python / Tkinter程序绘制一些图形。该程序有一个主菜单,菜单项用于绘制不同的数字。它工作得很好,但我遇到了一个问题。如果程序是绘制一个图形的一部分并且用户单击以绘制第二个图形,则程序绘制第二个图形,但是当它完成绘制第二个图形时,它返回并完成绘制第一个图形。我想要它做的是停止绘制第一个数字,即使第二个数字完成绘制,也不回去绘制第一个数字。我创建了一个更简单的示例程序来演示该场景。要在此程序中查看问题,请单击“绘图 - >红色”,然后在红色完成绘制之前单击“绘制 - >>蓝色”。如何让程序中止任何以前的绘图?以下是示例程序:

    from tkinter import *
    import random
    import math

    def line(canvas, w, h, p, i):
        x0 = random.randrange(0, w)
        y0 = random.randrange(0, h)
        x1 = random.randrange(0, w)
        y1 = random.randrange(0, h)
        canvas.create_line(x0, y0, x1, y1, fill=p.col(i))

    class Color:
        def __init__(self, r, g, b):
            self.red = r
            self.gre = g
            self.blu = b
        def hexVal(self, v):
            return (hex(v)[2:]).zfill(2)
        def str(self):
            return "#" + self.hexVal(self.red) + self.hexVal(self.gre) + self.hexVal(self.blu)

    class Palette:
        def __init__(self, n0, y):
            self.colors = []
            self.n = n0
            self.m = 0
            if y == "red":
                self.red()
            elif y == "blue":
                self.blue()
        def add(self, c):
            self.colors.append(c)
            self.m += 1
        def red(self):
            self.add(Color(127, 0, 0))
            self.add(Color(255, 127, 0))
        def blue(self):
            self.add(Color(0, 0, 127))
            self.add(Color(0, 127, 255))
        def col(self, i):
            k = i % (self.n*self.m)
            z = k // self.n
            j = k % self.n
            c0 = self.colors[z]
            c1 = self.colors[(z + 1) % self.m]
            t0 = (self.n - j)/self.n
            t1 = j/self.n
            r = int(math.floor(c0.red*t0 + c1.red*t1)) 
            g = int(math.floor(c0.gre*t0 + c1.gre*t1)) 
            b = int(math.floor(c0.blu*t0 + c1.blu*t1)) 
            c = Color(r, g, b)
            return c.str()

    def upd(canvas):
        try:
            canvas.update()
            return True
        except TclError:
            return False

    def tryLine(canvas, w, h, p, i, d):
        try:
            line(canvas, w, h, p, i)
            if i % d == 0:
                upd(canvas)
            return True
        except TclError:
            return False

    class MenuFrame(Frame):
        def __init__(self, parent):
            Frame.__init__(self, parent)
            self.parent = parent        
            self.initUI()
        def initUI(self):
            self.WIDTH = 800
            self.HEIGHT = 800
            self.canvas = Canvas(self.parent, width=self.WIDTH, height=self.HEIGHT)
            self.pack(side=BOTTOM)
            self.canvas.pack(side=TOP, fill=BOTH, expand=1)
            self.parent.title("Line Test")
            menubar = Menu(self.parent)
            self.parent.config(menu=menubar)
            self.parent.protocol('WM_DELETE_WINDOW', self.onExit)
            menu = Menu(menubar)
            menu.add_command(label="Red", command=self.onRed)
            menu.add_command(label="Blue", command=self.onBlue)
            menu.add_command(label="Exit", command=self.onExit)
            menubar.add_cascade(label="Draw", menu=menu)
            self.pRed = Palette(256, "red")
            self.pBlue = Palette(256, "blue")
        def onRed(self):
            # How to abort here any processes currently running?
            self.canvas.delete("all")
            for i in range(0, 7000):
                tryLine(self.canvas, self.WIDTH, self.HEIGHT, self.pRed, i, 100)
            upd(self.canvas)
        def onBlue(self):
            # How to abort here any processes currently running?
            self.canvas.delete("all")
            for i in range(0, 7000):
                tryLine(self.canvas, self.WIDTH, self.HEIGHT, self.pBlue, i, 100)
            upd(self.canvas)
        def onExit(self):
            self.canvas.delete("all")
            self.parent.destroy()

    def main():
        root = Tk()
        frame = MenuFrame(root)
        root.mainloop()

    if __name__ == '__main__':
        main()

1 个答案:

答案 0 :(得分:1)

这是一个简单的例子吗? ;)

您可以添加跟踪当前所选方法的变量,然后在完成for循环之前检查该变量是否存在。这是一个更简单的例子:

class Example(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)

        Button(self, text='Task A', command=self._a).pack()
        Button(self, text='Task B', command=self._b).pack()

        self.current_task = None # this var will hold the current task (red, blue, etc)

    def _a(self):

        self.current_task = 'a' # set the current task

        for i in range(1000):
            if self.current_task == 'a': # only continue this loop if its the current task
                print('a')
                self.update()

    def _b(self):

        self.current_task = 'b'

        for i in range(1000):
            if self.current_task == 'b':
                print('b')
                self.update()

root = Tk()
Example(root).pack()
root.mainloop()

请告诉我这是否有意义或不适合你。