Mauricio Mauricio - 1 year ago 100
Python Question

python tkinter: how to iterate with rather specific times (root.after not working)

im writing an autoclicker. ive sperated my clicks by time between mouse down and mouse up, and time between clicks (those times are stored in a csv file). basic idea, i want to run the program, and a window pops up with a start and a stop button(accomplished). i want to be able to hit start, and run a 'loop' of clicks ('iterating' through a list with the times saved) until i hit pause. i say 'loop' and 'iterate' because i know you cant run a seperate loop inside the main loop of tkinter. i tried used root.after to wait the time between clicks, then call a function that performs a click, but root.after doesnt take times that are as specific as i want. any ideas? heres the full script, and ill give a sample of the csv file as well. Im open to using other modules besides tkinter/other languages, if anything pops into your mind

import csv
import time
from tkinter import *
from PyWinMouse import *

root = Tk()
start_button = Button(root, text="start", width="7")
pause_button = Button(root, text="pause", width="7")

# holds times for clicks[time_between_up_down, time_between_clicks]
click_info = []
info_length = 0
clicker = Mouse()
paused = True
iterateVar = 0

def get_csv():
global click_info, info_length
file = open("times.csv", 'r')
reader = csv.reader(file, delimiter=",")
for row in reader:
info_length = len(click_info)

def click():
global iterateVar
if iterateVar < (info_length - 1) and paused is False:
iterateVar += 1

def pause_button_function(event):
global paused
paused = True

def start_button_function(event):
global paused
paused = False

pause_button.bind("<Button-1>", pause_button_function)
start_button.bind("<Button-1>", start_button_function)
root.after(float(click_info[iterateVar][1]), click)

this error is given:

Traceback (most recent call last):
"C:/Users/Owner/PycharmProjects/NaturalHumanBehaviorClickInfoGatherer/ActualClic", line 52, in <module>
root.after(float(click_info[iterateVar][1]), click)
File "C:\Users\Owner\AppData\Local\Programs\Python\Python35\lib\tkinter\", line 604, in after
return'after', ms, name)
_tkinter.TclError: bad argument "1.0223703384399414": must be cancel, idle, info, or an integer

snapshot of what the csv file looks like(ignore the 'False', that's for other stuff):


Answer Source

after method accepts time as a integer form (in milliseconds). You need to convert the value into int (multiplied by 1000 to mean milliseconds):

ms = int(click_info[iterateVar][1] * 1000)
root.after(ms, click)


  1. after make the fucntion called once. If you want to call it repeatedly, you need to call it again (maybe inside the callback click).
  2. Do not call time.sleep inside the callback function. It make UI freezing.
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download