【问题标题】:Python Tkinter button freezes program after using hotkeyPython Tkinter 按钮在使用热键后冻结程序
【发布时间】:2021-06-02 05:15:43
【问题描述】:

我正在尝试构建一个简单的自动点击程序,它具有开始/停止按钮和热键(使用 Tkinter 和 Pynput)。每当我使用开始按钮启动自动答题器时,它都能完美运行,我可以停止它。但是,当我使用热键启动自动点击器时,我无法使用停止按钮停止它,因为它会冻结整个程序。

这是我的 GUI 主类:

class App(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        super().__init__()
        self.parent = parent
        self.parent.bind("<Destroy>", self.exit)

        self.clicker = Clicker(Button.left, 1)
        self.clicker.start()

        self.kb = Keyboard("<shift>+s", self.start_click)
        self.kb.start()

        btn_box = ttk.Combobox(self, values=BUTTONS, state="readonly")
        btn_box.current(0)
        btn_box.pack()

        start = tk.Button(self, text="Start", command=self.start_click)
        start.pack()

        stop = tk.Button(self, text="Stop", command=self.stop_click)
        stop.pack()

        exit = tk.Button(self, text="Exit", command=self.exit)
        exit.pack()


    def start_click(self):
        self.clicker.start_click()


    def stop_click(self):
        print("e")
        self.clicker.stop_click()


    def exit(self, event=None):
        self.clicker.exit()
        self.parent.quit()

这些是我的 Clicker 和 Keyboard 类:

class Clicker(threading.Thread):
    def __init__(self, button, delay):
        super().__init__()

        self.button = button
        self.delay = delay

        self.running = False
        self.prog_running = True

        self.mouse = Controller()


    def start_click(self):
        print("start")
        self.running = True


    def stop_click(self):
        print("stop")
        self.running = False


    def exit(self):
        self.running = False
        self.prog_running = False


    def run(self):
        while self.prog_running:
            while self.running:
                self.mouse.click(self.button)
                time.sleep(self.delay)
            time.sleep(0.1)
class Keyboard(threading.Thread):
    def __init__(self, keybind, command):
        super().__init__()
        self.daemon = True
        self.hk = HotKey(HotKey.parse(keybind), command)


    def for_canonical(self, f):
        return lambda k: f(self.l.canonical(k))


    def run(self):
        with Listener(on_press=self.for_canonical(self.hk.press),
                      on_release=self.for_canonical(self.hk.release)) as self.l:
            self.l.join()

有谁知道为什么在使用热键后按下停止按钮时它会冻结?

【问题讨论】:

  • 它在我的 Windows 7 中运行良好。
  • 我使用的是 Windows 10,但它不适合我。
  • 它在我的笔记本上的 Windows 10 上也能正常工作。
  • 我想我知道为什么。每当我使用热键并在 GUI 内按住光标时,当我按下停止时它不会冻结。但是,如果我使用热键并将光标移动到别处,就会出现上述问题。我尝试使用self.parent.update() 更新根目录,但问题仍然存在。
  • 我想通了。这是我需要更新的框架。我刚刚在主框架类的stop_click 方法之前添加了一个self.update,它就像一个魅力!

标签: python multithreading tkinter


【解决方案1】:

我在使用 self.quit() 而不是 self.destroy() 时遇到了问题,但很可能不是你的情况。

使用self.bind()添加快捷方式可能是一种解决方案,

例如:

#Importing the tkinter module
from tkinter import *
#Creating a window
root = Tk()
#Creating a label
txt = Label(root, text="Opened! But I'm closing, you know...").grid(row=1, column=1)
#Defining an action and binding it(root is the window's name)
def actionn(*args):
    root.destroy()
root.bind('<Shift-S>', actionn)
#Showing the window and the label
root.mainloop()

你不能这样绑定 shift ,绑定self.parent.bind('&lt;Shift-S&gt;') 我猜它会冻结,因为分配的快捷方式不起作用......

【讨论】:

  • 问题是我想使用热键,即使根没有聚焦。据我所知,只有当 GUI 处于焦点时,这样的绑定才有效。这就是我使用 pynput 模块来处理热键的原因。不过感谢您的回答。 :))
猜你喜欢
  • 2021-07-04
  • 2021-06-24
  • 2018-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-27
  • 2016-12-18
  • 1970-01-01
相关资源
最近更新 更多