tkinter窗口停止响应

时间:2018-07-11 23:23:53

标签: python python-2.7 tkinter

我有此代码:

#python 2.7.15

import pyautogui
import time
import msvcrt
from threading import Thread
import win32api
import battle
import Tkinter
from Tkinter import *

#launcher pos x:868 y:975
#rocket pos x:829 y:936

def click():
        left = win32api.GetKeyState(0x01)
        while True:
                click = win32api.GetKeyState(0x01)
                if click != left:
                        left = click
                        #print(a)
                        if click < 0:
                                pyautogui.hotkey("ctrlleft")
                                time.sleep(1)

def rocket():
        rocket = True
        while rocket:
            pyautogui.hotkey("2")
            time.sleep(0.5)
            pyautogui.hotkey("7")
            time.sleep(20)

root = Tk()
root.geometry("300x200")
root.title("Bot options")
root = Tkinter.Button(root, text = "Click me", command = rocket)
root.pack()
root.mainloop()


"""key = msvcrt.getche()
if key == 'z':
        click()
elif key == 'x':
    if __name__ == '__main__':
            Thread(target = click).start()
            Thread(target = battle.battle).start()
            Thread(target = rocket).start()"""

问题是,在运行时,当我单击创建的窗口内的“单击我”按钮时,该窗口停止响应。我尝试将command = rocket更改为command = rocket(),但是没有弹出窗口并且功能开始起作用

1 个答案:

答案 0 :(得分:0)

您不能在事件处理程序中执行一个永远运行的while True:循环,或者长时间运行的任何循环。

如果这样做,则永远不会将控制权返回到tkinter事件循环。但是事件循环是程序处理鼠标移动,按键和操作系统中重要消息之类的方式的过程。因此,如果您不让它运行,则GUI会挂起,最终您会得到沙滩球,沙漏或怀表,或者Windows用来表示“无响应”的任何东西。


因此,您需要执行以下操作:

def rocket():
    pyautogui.hotkey("2")
    root.after(500, rocket2)

def rocket2():
    pyautogui.hotkey("7")
    root.after(20000, rocket)

现在,不是永远循环,而是在等待半秒后阻塞整个程序,然后在等待20秒后再次阻塞整个程序,它只是快速执行了一些操作,要求tkinter在0.5秒内运行其余代码,然后返回

当然,您需要在click中做类似的事情。


另一种不需要使用这种循环的方法是使用线程。 (您已经导入了threading,但未对其进行任何操作。)

线程并不总是一个好的解决方案。例如,不允许您从后台线程访问任何tkinter窗口小部件,并且在大多数程序中,您需要执行诸如从Entry获取值并更新Label中的文本之类的操作。等等。但是在这里,您没有这样做。 pyautogui似乎是一种从后台线程也可能无法使用的库,但是我没有检查过;如果它是线程安全的,则可以轻松更改您的函数。

您想调用一个在后台线程中启动rocket的函数,而不是直接调用rocket

def rocket():
    rocket = True
    while rocket:
        pyautogui.hotkey("2")
        time.sleep(0.5)
        pyautogui.hotkey("7")
        time.sleep(20)

def start_rocket():
    th = threading.Thread(target=rocket)
    th.start()

# …

root = Tkinter.Button(root, text = "Click me", command = start_rocket)