将看门狗与 Tkinter 一起使用 [英] Use watchdog along with Tkinter

查看:43
本文介绍了将看门狗与 Tkinter 一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有一个小脚本来监视文件的更改/修改,如果文件被更改,它会用它做一堆事情,比如:

So I have a small script which monitors files for changes/modifications, if the file is changed it does a bunch of stuff with it like:

class Event(LoggingEventHandler):
def dispatch(self, event):
    #Do something here

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s - %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    event_handler = Event()
    observer = Observer()
    observer.schedule(event_handler, my_path, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

而且效果很好.但是我有另一个带有一堆 Tkinter 小部件的脚本(带有 mainloop() 的典型 tk 应用程序).现在,当用户按下某个按钮时,我想像以前一样调用看门狗来监视文件更改,然后调用 dispatch() 对它执行一堆操作并更新一些 tkinter ui 小部件,例如进度条相同的脚本.

And it works great. But I have another script with bunch of Tkinter widgets(typical tk app with mainloop()). Now, When user presses a certain button I want to call watchdog to monitor file changes like before and call dispatch() which does a bunch of stuff to it and updates some tkinter ui widgets like progressbars all in the same script.

这个 GUI 的东西很新,无法弄清楚如何使看门狗循环和 root.mainloop 一起工作.怎么办?

Pretty new to this GUI stuff, can't figure out how to make watchdog loop and root.mainloop work together. How can it be done?

推荐答案

Watchdog 在自己的线程中运行,因此您无需做太多事情.如果要根据事件修改 GUI,则应设置线程安全队列.Tkinter 小部件不应被多个线程修改,因此常见模式是使用线程安全队列在线程之间进行通信.

Watchdog runs in its own thread, so there's not much you need to do. If you want to modify the GUI based on an event, you should set up a thread-safe queue. Tkinter widgets shouldn't be modified by more than one thread so the common pattern is to use a thread safe queue to communicate between threads.

以下示例将看门狗事件放置在队列中,并在检测到看门狗事件时使用 event_generate 将信号从观察者发送到 GUI.我不确定以下内容是否适用于所有情况,因为我目前只能访问一个 linux 机器来测试它.但是,它在 linux 上似乎可以正常工作.

The following example places a watchdog event on a queue and uses event_generate to send a signal from the observer to the GUI whenever a watchdog event is detected. I don't know with absolute certainty that the following will work in all cases, because I only have access to a linux box to test it at the moment. However, it seems to work ok on linux.

import Tkinter as tk
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

from Queue import Queue
import sys

class CustomHandler(FileSystemEventHandler):
    def __init__(self, app):
        FileSystemEventHandler.__init__(self)
        self.app = app
    def on_created(self, event): app.notify(event)
    def on_deleted(self, event): app.notify(event)
    def on_modified(self, event): app.notify(event)
    def on_moved(self, event): app.notify(event)

class App(object):
    def __init__(self):
        path = sys.argv[1] if len(sys.argv) > 1 else "/tmp"
        handler = CustomHandler(self)
        self.observer = Observer()
        self.observer.schedule(handler, path, recursive=True)

        self.queue = Queue()
        self.root = tk.Tk()

        self.text = tk.Text(self.root)
        self.text.pack(fill="both", expand=True)

        self.text.insert("end", "Watching %s...\n" % path)

        self.root.bind("<Destroy>", self.shutdown)
        self.root.bind("<<WatchdogEvent>>", self.handle_watchdog_event)

        self.observer.start()

    def handle_watchdog_event(self, event):
        """Called when watchdog posts an event"""
        watchdog_event = self.queue.get()
        print("event type:", type(watchdog_event))
        self.text.insert("end", str(watchdog_event) + "\n")

    def shutdown(self, event):
        """Perform safe shutdown when GUI has been destroyed"""
        self.observer.stop()
        self.observer.join()

    def mainloop(self):
        """Start the GUI loop"""
        self.root.mainloop()

    def notify(self, event):
        """Forward events from watchdog to GUI"""
        self.queue.put(event)
        self.root.event_generate("<<WatchdogEvent>>", when="tail")

app = App()
app.mainloop()

这篇关于将看门狗与 Tkinter 一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆