【问题标题】:How to stop other processes or finish processes in Python / Tkinter program如何在 Python / Tkinter 程序中停止其他进程或完成进程
【发布时间】:2014-06-21 10:54:17
【问题描述】:

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

    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()

【问题讨论】:

    标签: python tkinter


    【解决方案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()
    

    如果这没有意义或不适合你,请告诉我。

    【讨论】:

    • 我的原始程序中有更多的数字运算。您的示例效果很好。我添加了一个锁以防止任务同时设置变量,尽管这可能永远不会发生。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-17
    • 2019-07-12
    • 2012-08-09
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    相关资源
    最近更新 更多