Execute other statements while a 'While' loop runs in Python

167 views Asked by At

I'm writing a small application on Python.

I have a While loop executing indefinitely while a global variable is set to True, but I want to be able to set this same variable as False clicking another button (I'm using dearpygui to make a interface).

Here's the main function code:

import pyautogui
import time

global enabled
enabled = True

def stopautoclick():
    listglobals = globals()
    listglobals["enabled"] = False

def autoclick(button, delay, coordX, coordY):
    listglobals = globals()
    mousebutton = button
    match mousebutton:
        case "Esquerdo":
            mousebutton = "left";
        case "Direito":
            mousebutton =  "right";
        case "Centro":
            mousebutton = "middle";
    print(mousebutton)
    time.sleep(delay)
    while listglobals["enabled"]:       
            pyautogui.click(x=coordX, y=coordY, button=mousebutton);
            time.sleep(delay);

See that enabled global variable? So, I created a button to stop that while iteration by setting this global variable to False, like this:

dpg.add_button(label="Parar Auto Click", callback=lambda: stopautoclick)

Problem is nothing in my code executes while the while loop iterates. Therefore, when I click the stop button, it doesn't execute anything and the value of the global variable enabled is not changed.

Even tried using the asyncio library to make the code execute asynchronously, but no success.

TL;DR: I want to be able to stop a loop (be a while or a for loop, doesn't matter) by clicking a button in my window interface, but while the loop is running, nothing else executes.

1

There are 1 answers

0
João Textor On BEST ANSWER

Using the knowledge of this answer on another question, I was able to solve my issue.

In short, I started the autoclick function using a Thread and used an Event() to perform the loop (while not condition.is_set()), and on the my "stop button" I just called condition.set()

This is the code: autoclick.py:

import pyautogui
import time
from threading import Event

enabled = Event()

def autoclick(button, delay, coordX, coordY):
    mousebutton = button
    match mousebutton:
        case "Esquerdo":
            mousebutton = "left";
        case "Direito":
            mousebutton =  "right";
        case "Centro":
            mousebutton = "middle";
    print(mousebutton)
    time.sleep(delay)
    while not enabled.is_set():   
        print(enabled)
        pyautogui.click(x=coordX, y=coordY, button=mousebutton);
        time.sleep(delay);

pyclick_ui.py:

import dearpygui.dearpygui as dpg
from threading import Event, Thread

from delayWithMessage import delayWithMessage
from autoclick import *
from getmousecoords import getmousecoords

[...some code]

def handleAutoClickButton(mousebutton, delay, coordx, coordy):
    tStartAutoclick = Thread(target=autoclick, args=(mousebutton, delay, coordx, coordy)).start()

def main():

   [...some code]

   dpg.add_button(label="Iniciar Auto Click", callback=lambda btn, delay, cX, cY: handleAutoClickButton(listglobals["mouseButton"], listglobals["clickDelay"], listglobals["coordX"], listglobals["coordY"]), tag="btnstart")
   dpg.add_button(enabled=False, label="Parar Auto Click", callback=lambda: enabled.set(), tag="btnstop")

[...rest of the code]

That way, when I click the second button, the enabled variable is set() and then the while loop will stop.

If any of you have a better approach, I'll be happy to read.