在Python 3.4中的mainloop之后,在tkinter中继续运行函数

时间:2014-11-27 23:42:42

标签: python-3.x graphics tkinter

我想要做的是在屏幕中心的单个像素中着色,然后随机选择一个相邻的像素并将其着色,然后重复直到满足某些条件 - 任何时间或屏幕等已满,或者在一定数量的像素已满后。这个结局并不重要,我还没有那么远,我想我可以自己设法解决这个问题。

我对tkinter没有经验,但我认为这是展示这一点的最佳方式,因为我真的没有别的办法。因此,我在这里找到的示例中复制粘贴(并稍微编辑)了一些代码(主要是像Canvas,PhotoImage等tkinter函数)。

我的代码在运行时所做的很难说 - 它使用CPU看起来无限可能,并慢慢增加其内存使用量,但似乎没有做任何事情。没有窗口打开,IDLE解释器像往常一样在计算某些东西时转到空白行。当被杀死时,窗口打开,并在右下角显示一个带有一点黑色斑点的白页 - 好像程序已完成它的意图,但没有显示它发生,并从错误的地方开始。

所以:

  • 为什么会这样做?
  • 我应该怎样做才能使我的计划有效?
  • 更好的编码方式,改变你想要的东西(即没有tkinter,不同的算法等)?

    来自tkinter import Tk,Canvas,PhotoImage,mainloop     来自随机进口randrange     从时间导入睡眠

    def choose_pixel(pixel_list):
    
        possible_pixels = []
    
        for x in pixel_list:
    
            #adjacent pixels to existing ones
    
            a = [x[0] + 1, x[1]]
    
            b = [x[0] - 1, x[1]]
    
            c = [x[0], x[1] + 1]
    
            d = [x[0], x[1] - 1]
    
            #if a not in pixel_list:
    
            possible_pixels.append(a)
    
            #if b not in pixel_list:
    
            possible_pixels.append(b)
    
            #if c not in pixel_list:
    
            possible_pixels.append(c)
    
            #if d not in pixel_list:
    
            possible_pixels.append(d)
    
        pixel_choosing = randrange(len(possible_pixels))
    
        final_choice = possible_pixels[pixel_choosing]
    
        return final_choice
    
    def update_image(img_name, pixel):
    
        img.put("#000000", (pixel[0], pixel[1]))
    
    WIDTH, HEIGHT = 320, 240
    
    window = Tk()
    
    #create white background image
    
    canvas = Canvas(window, width=WIDTH, height=HEIGHT, bg="#ffffff")
    
    canvas.pack()
    
    img = PhotoImage(width=WIDTH, height=HEIGHT)
    
    canvas.create_image((WIDTH, HEIGHT), image=img, state="normal")
    
    first_pixel = [int(WIDTH/2), int(HEIGHT/2)]
    
    pixel_list = [first_pixel]
    
    img.put("#000000", (first_pixel[0], first_pixel[1]))
    
    canvas.pack()
    
    runs = 0
    
    while True:
    
        next_pixel = choose_pixel(pixel_list)
    
        pixel_list.append(next_pixel)
    
        window.after(0, update_image, img, next_pixel)
    
        canvas.pack()
    
        runs+=1
    
    
    window.mainloop()
    

1 个答案:

答案 0 :(得分:2)

在tkinter中定期运行某些东西的模式是编写一个执行任何你想做的事情的函数,然后它做的最后一件事就是使用after在将来再次调用自己。它看起来像这样:

import tkinter as tk
...

class Example(...):
    def __init__(self, ...):
        ...
        self.canvas = tk.Canvas(...)
        self.delay = 100 # 100ms equals ten times a second
        ...
        # draw the first thing
        self.draw_something()

    def draw_something(self):
        <put your code to draw one thing here>
        self.canvas.after(self.delay, self.draw_something)

在函数绘制之后,它会安排自己在将来再次运行。延迟定义了下一次呼叫之前等待的时间。数字越小,运行得越快,但使用的CPU越多。这是有效的,因为在调用时间after和时间过去之间,事件循环(mainloop)可以自由处理其他事件,例如屏幕重绘。

虽然您可能认为这看起来像递归,但它并不是因为它没有进行递归调用。它只是将一个作业添加到主循环定期检查的队列中。