Home > Back-end >  pyautogui does not click based on slider/scale values in Tkinter
pyautogui does not click based on slider/scale values in Tkinter

Time:08-09

How I can make pyautogui click based on scale value in Tkinter ?

For example if the scale value is 10 the click delay (with pyautogui.PAUSE) should be of 0.1 it represent 10 clicks per second and if the scale value is 15 the delay should be of 0.15 => 15 clicks per second.

The problem clicks are not activated depending on the scale value

I also can't put root.mainloop() anywhere else than in the While True loop although I would have liked to put it at the very end of the program but in this case I would have to replace while True by "while "normal" == root.state()" (to stop the loop as soon as the Tkinter window closes) which doesn't work either

The code :

import mouse  
import threading
import pyautogui
from tkinter import *
from tkinter import ttk

root = Tk()
root.geometry('500x400')
bovar = IntVar()

def func(*args):
    if bovar.get() == 10:
        pyautogui.PAUSE = 0.1
    elif bovar.get() == 11:
        pyautogui.PAUSE = 0.11
    elif bovar.get() == 12:
        pyautogui.PAUSE = 0.12
    elif bovar.get() == 13:
        pyautogui.PAUSE = 0.13
    elif bovar.get() == 14:
        pyautogui.PAUSE = 0.14
    else: 
        pyautogui.PAUSE = 0.15
   

scale = Scale(root,orient=HORIZONTAL,from_=10,to=15,variable=bovar,command=func)
label = Label(root,text='CPS:')
label.pack(side=TOP)
scale.pack()

func()
root.mainloop() 


def repeat_function(kill_event):
  
    while not kill_event.is_set():
            
           
            pyautogui.click()

while True:
   
    kill_event = threading.Event()
    
    new_thread = threading.Thread(target=lambda: repeat_function(kill_event))

   
    mouse.on_button(new_thread.start, (), mouse.RIGHT, mouse.DOWN)
    
    mouse.on_button(kill_event.set, (), mouse.RIGHT, mouse.UP)

   
    mouse.wait(mouse.RIGHT, mouse.UP)
   
    mouse.unhook_all()

 

CodePudding user response:

root.mainloop() starts an infinite loop that waits for actions on the tkinter window and responds to them. Thus, any code you write under this call isn't going to execute until you close tkinter. If you want something to run simultaneously with this tkinter loop, it will have to run in another thread. Your logic of determining PAUSE is also a little flawed. A pause of 0.15 seconds doesn't mean it will click 15 times per second, but 1/0.15 times.

import mouse  
import threading
import pyautogui
from tkinter import *
from tkinter import ttk

def convert_to_pause(clicks_per_second):
    clicks_per_second = min(clicks_per_second, 15)
    return 1 / clicks_per_second

def repeat_function(kill_event, int_var):
    while not kill_event.is_set():
        pyautogui.PAUSE = convert_to_pause(int_var.get())
        pyautogui.click()

def hotkey_thread_loop(int_var):
    # The loop you already have, we just need to run it in a separate thread
    # We pass it the IntVar from the Scale so that it can dynamically read its value
    while True:
        kill_event = threading.Event()
        # Here we also pass the IntVar to access its value in the new thread
        new_thread = threading.Thread(target=lambda: repeat_function(kill_event, int_var))
        mouse.on_button(new_thread.start, (), mouse.RIGHT, mouse.DOWN)
        mouse.on_button(kill_event.set, (), mouse.RIGHT, mouse.UP)
        mouse.wait(mouse.RIGHT, mouse.UP)
        mouse.unhook_all()
        

# Start the main program
if __name__ == "__main__":
    # Set up all tkinter stuff
    root = Tk()
    root.geometry('500x400')
    bovar = IntVar()

    scale = Scale(root,orient=HORIZONTAL,from_=10,to=15,variable=bovar,command=func)
    label = Label(root,text='CPS:')
    label.pack(side=TOP)
    scale.pack()
    
    # Create the thread to manage hotkey pressing and start it
    # Set daemon=True to have it terminate when main program ends
    hotkey_thread = threading.Thread(target=lambda: hotkey_thread_loop(bovar),
                                     daemon=True)
    hotkey_thread.start()
    
    # Start the tkinter application, the ininite loop
    root.mainloop()

    # Any code put here (below mainloop()) will not execute while tkinter runs,
    # don't try to implement more logic here
  • Related