Python 3.x 在Python3.4的mainloop之后在tkinter中连续运行函数

Python 3.x 在Python3.4的mainloop之后在tkinter中连续运行函数,python-3.x,graphics,tkinter,Python 3.x,Graphics,Tkinter,我想做的是在屏幕中央的一个像素上色,然后随机选择一个相邻的像素并上色,然后重复,直到满足某个条件,比如时间,或者屏幕满了,或者在一定数量的像素满了之后。这个结局并不太重要,我还没走到那一步,我想我可以自己解决这个问题 我没有使用tkinter的经验,但我认为这是最好的展示方式,因为我没有其他方式。因此,其中一些代码(主要是tkinter函数,如Canvas、PhotoImage等)是从我在这里找到的示例中复制粘贴的(并经过轻微编辑) 我的代码在运行时会做什么很难说——它似乎无限期地尽可能多地使用

我想做的是在屏幕中央的一个像素上色,然后随机选择一个相邻的像素并上色,然后重复,直到满足某个条件,比如时间,或者屏幕满了,或者在一定数量的像素满了之后。这个结局并不太重要,我还没走到那一步,我想我可以自己解决这个问题

我没有使用tkinter的经验,但我认为这是最好的展示方式,因为我没有其他方式。因此,其中一些代码(主要是tkinter函数,如Canvas、PhotoImage等)是从我在这里找到的示例中复制粘贴的(并经过轻微编辑)

我的代码在运行时会做什么很难说——它似乎无限期地尽可能多地使用CPU,并缓慢地增加内存使用量,但似乎什么都不做。没有打开任何窗口,空闲的解释器将转到一个空行,这与计算某些内容时一样。死机时,窗口打开,并显示一个白色页面,右下角有一个小黑色斑点-好像程序已经完成了它的本意,但没有显示它正在发生,并且在错误的位置启动

因此:

  • 为什么会这样
  • 我应该怎么做才能使我的程序正常工作
  • 有什么更好的编码方法,可以随意改变很多东西(例如,没有tkinter,不同的算法等等)

    从tkinter导入Tk、画布、照片图像、mainloop 从随机输入范围 从时间上导入睡眠

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

在tkinter中定期运行某个程序的模式是编写一个函数,该函数可以执行您希望它执行的任何操作,然后它所做的最后一件事就是在以后使用
来再次调用自己。它看起来像这样:

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)
将tkinter作为tk导入
...
类示例(…):
定义初始化(自…):
...
self.canvas=tk.canvas(…)
self.delay=100#100ms等于每秒十次
...
#画第一件事
self.画些什么
def draw_某物(自身):
self.canvas.after(self.delay,self.draw_某物)
在函数绘制某些内容后,它会安排自己在将来再次运行。延迟定义了下一次呼叫前的大致等待时间。数字越小,运行速度越快,但使用的CPU越多。这是可行的,因为在调用
之后的
时间和经过的时间之间,事件循环(
mainloop
)可以自由处理其他事件,例如屏幕重画


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