如何使用tkinter(ttk)按钮同时运行包含while循环的两个函数

时间:2016-02-15 05:26:01

标签: python multithreading lambda tkinter ttk

我目前正在开发一个基本机器人项目,我决定让机器人随机移动,同时随机播放随机音符,从而构成自己的音乐。我目前有两个while循环(一个在function1中,另一个在function2中),我很好奇我如何在GUI上按下tkinter(ttk)按钮同时运行这两个循环。我相信这将包括线程,但我没有太多经验,任何帮助我弄清楚并走上正确轨道的事情都会很棒。

1 个答案:

答案 0 :(得分:0)

这里有一个

from tkinter import *
from tkinter.scrolledtext import ScrolledText
import asyncio
from random import random


async def loop1(text: ScrolledText):
    while True:
        text.insert(END, 'loop1\n')
        text.see('end')
        await asyncio.sleep(random())


async def loop2(text: ScrolledText):
    while True:
        text.insert(END, 'loop2\n')
        text.see('end')
        await asyncio.sleep(random())


async def run_tk(root, interval=0.05):
    try:
        while True:
            root.update()
            await asyncio.sleep(interval)
    except TclError as e:
        if "application has been destroyed" not in e.args[0]:
            raise


def main():
    root = Tk()
    text = ScrolledText(root)
    text.grid(column=0, row=0, sticky=NW+SE)

    asyncio.ensure_future(loop1(text))
    asyncio.ensure_future(loop2(text))

    loop = asyncio.get_event_loop()
    loop.run_until_complete(run_tk(root))

if __name__ == "__main__":
    main()

在你的应用程序中,你会弹奏音符(或和弦),然后等待一段时间,这对asyncio.sleep()来说是完美的。通常,在并发应用程序中,您等待某些外部资源为您提供数据,而在这些情况下asyncio只有在您拥有与asyncio完全合作的库时才能真正起作用。在你的情况下,你控制了节目,所以asyncio对你来说是完美的(假设你的播放的音符在持有期间不会阻止注意;否则它不会工作,你必须使用线程。)

另一方面,像这样手动抽取tk事件循环肯定会引起一些人的注意,并可能引起嘲笑。

如果你想进入穿线路线,这也很好,但要确保通过作业Queue传递线程和主循环之间的所有通信。它变得有些复杂,而你可以用asyncio快速启动并运行。