Python 使用 tkinter 同时循环两个循环

Posted

技术标签:

【中文标题】Python 使用 tkinter 同时循环两个循环【英文标题】:Python two loops simultaneously with tkinter 【发布时间】:2021-04-09 10:34:16 【问题描述】:

我有两个框架的 Tkinter GUI 应用程序。我想要做的是同时运行两个无限循环。 而一个循环可以从另一个循环中获取数据。

我有 main.py

class Main(tk.Tk):

    def __init__(self, *args, **kwargs):
        
        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)
.....
.....

app = Main()
app.mainloop()

然后两个帧首先是 startPage.py,其中只有一个按钮重定向到experimentPage.py。 最后一个重要的框架。 ExperimentPage.py 这两个循环在哪里。

class experimentPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        // ButtonX that start two loops //
    .... 
    ....
    def loop1(self)
    def loop2(self) // Getting data from loop1

我要做的基本上是同时运行loop1和loop2,而loop2可以从loop1获取数据。现在我不确定如何实现这一点,我所有的尝试都失败了。

如果我理解正确,我必须使用 asyncio 修改 main.py mainloop。并用 asyncio 修改实验页面。使用async def loop1(self) 就可以了。但无论我尝试什么都以错误结束。

编辑 1 - 在这我只有一个循环。但是在那个循环中,我从眼球追踪器获取数据,将它们绘制在屏幕上并进行一些计算。问题是它从我实际查看的位置和绘制的内容中得到了一些延迟。这就是为什么我想要两个循环。一个用于来自眼球追踪器的实时数据。还有一个用于绘图和计算的东西。

编辑 2 - 问题是我不知道如何正确编辑 mainloop 以运行异步任务,因为我发现的所有内容也都与线程有关。我尝试了 app.asyncio.mainloop() 之类的东西,它以 AttributeError 之类的错误结束:'_tkinter.tkapp' object has no attribute 'asyncio' 我只使用 python 几天,所以我可能会遗漏一些基本的东西。

【问题讨论】:

您能否更具体地了解循环,而不仅仅是 tkinter。为什么需要两个循环?他们在做什么单循环不会做的事情。 您要解决的问题是什么?您的问题暗示了一种有缺陷的方法。 感谢您的反应,我将它们添加为对我的问题的编辑。 为什么不想使用线程?这不是显而易见的解决方案吗? @wuerfelfreak 我认为异步方法比线程更容易,这就是我决定使用异步的原因。但我可能会切换到线程感谢您的评论。 【参考方案1】:

可以这样使用:

def loop2(self):
    while !self.stopSignal:
        #do stuff here

def start_loops():
    self.stopSignal = False
    
    thread = threading.Thread(target=loop2, args=(self,))
    thread.start()
    loop1(self)
    self.stopSignal = True
    thread.join()

【讨论】:

【参考方案2】:

您可以使用计时器来实现这一点。

在 Tkinter 中,你可以使用tk.after

from tkinter import *
import cv2
from PIL import Image,ImageTk


def take_snapshot():
    print("some one like it")

def video_loop():
    success, img = camera.read()  # read image with camera
    if success:
        # cv2.waitKey(1) # this line is not necessary in Tkinter
        cv2image = cv2.cvtColor(img, cv2.COLOR_BGR2RGBA) #convert color from BGR to RGBA
        current_image = Image.fromarray(cv2image) #convert to Image for Tkinter
        imgtk = ImageTk.PhotoImage(image=current_image)
        panel.imgtk = imgtk
        panel.config(image=imgtk)
        root.after(1, video_loop)


camera = cv2.VideoCapture(0)    #camera

root = Tk()
root.title("opencv + tkinter")
#root.protocol('WM_DELETE_WINDOW', detector)

panel = Label(root)  # initialize image panel
panel.pack(padx=10, pady=10)
root.config(cursor="arrow")
btn = Button(root, text="Like!", command=take_snapshot)
btn.pack(fill="both", expand=True, padx=10, pady=10)

video_loop()

root.mainloop()
# before quit the program, release all the resources
camera.release()
cv2.destroyAllWindows()

【讨论】:

以上是关于Python 使用 tkinter 同时循环两个循环的主要内容,如果未能解决你的问题,请参考以下文章

Python在tkinter中发送websocket消息

如何在循环链表中查找循环起始节点?

Python中的线程建议

Python数据结构与算法(2.5)——循环链表

Python D-Bus 和 Tkinter 主循环集成

Python实现约瑟夫生者死者游戏可视化(单向循环链表实现)