首页 > 解决方案 > 在窗口聚焦时获取用户输入,从文件输入是否聚焦

问题描述

这是一个多线程问题,但不是真的。我有一个 Python Tkinter Toplevel窗口(测试了 Python 2.7 和 3.5):

wman 删除新的 windows.png

第二个按钮定义为:

    btn2 = tk.Button(button_frame, text='Remove new', \
                     command=self.remove)
    btn2.pack(side=tk.LEFT)

当按下按钮时调用此函数:

def remove(self):
    ''' Remove windows on monitor now that weren't there at start '''
    new_windows = []
    new_windows_cnt = 0
(... SNIP out boring stuff ...)

上面的代码在窗口具有焦点并且用户单击按钮时有效。现在我正在创建这个 Ubuntu Unity 键盘自定义快捷键:

Ubuntu自定义键盘快捷键.png

注意:快捷方式似乎不起作用,但这不是什么大问题


现在问题的并行处理部分

创建一个在顶层窗口没有焦点时连续运行的函数:

def parallel_processing(self)
    while (not_toplevel_destroyed):
        try:
            f = open("/tmp/w")
            self.remove()
        except IOError:
            pass         # TODO: Test if IOError is even, else delete this and above
        finally:
            f.delete()

        time.sleep(.1)

注意:如果这个新函数在Toplevel窗口有焦点时也运行是可以的,在这种情况下它将是一个 1/10 秒延迟的加速键。

btn2打包后如何调用这个新函数?

当Toplevel被按钮 1 破坏时,我如何杀死这个新功能,其中包含:

btn = tk.Button(button_frame, text='Close', \
                command=self.toplevel.destroy)
btn.pack(side=tk.LEFT)

解决了!!!

下面接受的答案有效,但我的概念草案中有一些错误。这是最终代码:

import os
import time
(... SNIP ...)

        button_frame = tk.Frame(self.toplevel)
        button_frame.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)

        btn = tk.Button(button_frame, text='Close', \
                        command=self.close_toplevel)
        btn.pack(side=tk.LEFT)

        btn2 = tk.Button(button_frame, text='Remove new', \
                         command=self.remove)
        btn2.pack(side=tk.LEFT)

        self.toplevel_active = True
        self.parallel_processing()

    def close_toplevel(self):
        self.toplevel_active = False
        time.sleep(0.2)
        self.toplevel.destroy()

    def parallel_processing(self):
        if os.path.exists("/tmp/w"):
            os.remove("/tmp/w")
            self.remove()

        if self.toplevel_active:
            root.after(100, self.parallel_processing) 

    def remove(self):
        ''' Remove windows on monitor now that weren't there at start '''
        new_windows = []
        new_windows_cnt = 0
(... SNIP ...)

这是测试证明:

$ echo 1 > /tmp/w

$ ll /tmp/w
ls: cannot access '/tmp/w': No such file or directory

该文件不存在,因为 python 程序正在运行。该parallel_processing(self)函数似乎增加了不到 1% 的 CPU 负载。

标签: pythontkinterparallel-processing

解决方案


我不确定我是否理解问题。

您可以使用root.after而不是while并且sleep它不会阻塞root.mainloop()

def parallel_processing(self)
    try:
        f = open("/tmp/w")
        self.remove()
    except IOError:
        pass         # TODO: Test if IOError is even, else delete this and above
    finally:
        f.delete()

    if self.not_toplevel_destroyed:
        root.after(100, self.parallel_processing) 

btn2 = tk.Button(button_frame, text='Remove new', command=self.remove)
btn2.pack(side=tk.LEFT)

self.not_toplevel_destroyed = True
self.parallel_processing()

您可以分配将设置not_toplevel_destroyed = False为停止功能的功能并等待几毫秒以确保,然后它将破坏窗口。

def close_app(self)
    self.not_toplevel_destroyed = False
    time.sleep(0.2)
    self.toplevel.destroy()

btn = tk.Button(button_frame, text='Close', command=self.close_app)
btn.pack(side=tk.LEFT)

推荐阅读