Reputation:
I have this code:
#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()"""
The problem is that when running and I click the Click me button inside the window that is created, the window stops responding. I have tried changing command = rocket
to command = rocket()
but no window pops up and function starts working
Upvotes: 0
Views: 708
Reputation: 365707
You can't do a while True:
loop that just runs forever—or anything at all that runs for a long time—in an event handler.
If you do, you never return control to the tkinter event loop. But the event loop is how your program processes things like mouse moves and key presses and important messages from the OS. So, if you don't let it run, your GUI hangs, and eventually you get a beachball or hourglass or pocket watch or whatever Windows uses to mean "unresponsive".
So, you need to do something like this:
def rocket():
pyautogui.hotkey("2")
root.after(500, rocket2)
def rocket2():
pyautogui.hotkey("7")
root.after(20000, rocket)
Now, instead of looping forever, blocking the whole program while it waits half a second and then again while it waits 20 seconds, it just does something quick, asks tkinter to run the rest of the code in 0.5 seconds, then returns.
And you need to do something similar in click
, of course.
A different option, that doesn't require turning your loops inside-out like this, is to use threads. (You've already imported threading
, but you're not doing anything with it.)
Threads aren't always a good solution. For example, you're not allowed to access any tkinter widgets from a background thread, and in most programs, you need to do things like get the value from an Entry
and update the text in a Label
and so on. But here, you're not doing that. pyautogui
seems like the kind of library that also might not be usable from a background thread, but I haven't checked; if it's thread-safe, your function can be changed easily.
Instead of calling rocket
directly, you want to call a function that starts rocket
in a background thread:
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)
Upvotes: 1