While Loop In Tkinter with Pyautogui

Viewed 263

I'm trying to create a mouse loop application, I can get the start button to work inside the loop, however the end button seems to crash tkinter instead of close the application.

any advise would be appreciated

import pyautogui
from tkinter import *
import sys


window = Tk()


def start_loop():
    while True:
        pyautogui.moveTo(3131, 891, 1)
        pyautogui.PAUSE = 180
        pyautogui.moveTo(3128, 434, 1)
        

b1 = Button(window, text="Start Mouse", command=start_loop)
b1.grid(row=0, column=0)



def end_loop():
    print(sys.exit())
    
b2 = Button(window, text="Stop Mouse", command=end_loop)
b2.grid(row=0, column=1)


window.mainloop()
2 Answers

You should use after function.

In tkinter, it should check each component of interfaces with loop (I mean mainloop). However, if you use while True:, then the GUI cannot check the reactions about the other functions or interfaces like Button.

So, your program can be downed.

import pyautogui
from tkinter import *
import sys


window = Tk()


def start_loop():
    pyautogui.moveTo(3131, 891, 1)
    pyautogui.PAUSE = 1.8
    pyautogui.moveTo(3128, 434, 1)
    window.after(180, start_loop) //after(ms_for_delay, function)
        

b1 = Button(window, text="Start Mouse", command=start_loop)
b1.grid(row=0, column=0)


def end_loop():
    sys.exit()
    
b2 = Button(window, text="Stop Mouse", command=end_loop)
b2.grid(row=0, column=1)


window.mainloop()

Try this code.

This can also be achieved using threading.

It will consume more resources, but I think it would be less "clunky" as a end result.

I added comments about the timing and some print statements to track what is happening:

import pyautogui
from tkinter import *
import threading
import sys
import time


window = Tk()

t = False

def start_thread():
    """Starts the Mouse thread"""
    global t
    if t:
        return
    t = threading.Thread(target = start_loop)
    setattr(t, "flag", False)
    t.start()
    print("Mouse thread Started")
    
def start_loop():
    """Loop that moves the mouse"""
    t = threading.current_thread()
    time.sleep(0.1) # Just for better printing
    while True:
        print("Mouse thread Running")
        pyautogui.moveTo(3131, 891, 1)
        # Not sure you wanted to adjust the pyautogui time to 180, or just wait 180 seconds.
        #pyautogui.PAUSE = 180
        for x in range(180):
            time.sleep(1)
            flag = getattr(t, "flag")
            if flag:
                print("Mouse thread Stopped")
                return
        pyautogui.moveTo(3128, 434, 1)

def end_loop():
    """Ends the mouse loop"""
    global t
    if not t:
        return
    setattr(t, "flag", True)
    while t.is_alive():
        time.sleep(0.1)
    t = False
        

b1 = Button(window, text="Start Mouse", command=start_thread)
b1.grid(row=0, column=0)
    
b2 = Button(window, text="Stop Mouse", command=end_loop)
b2.grid(row=0, column=1)

window.mainloop()
Related