Search code examples
tkintertkinter-button

how to make a tkinter button click itself?


I'm trying to make a clicker game for my friend. I just want to know how to make a button that when clicked, clicks another button. Here is some of the code:

from tkinter import *
import time
root = Tk()
root.geometry('600x600')
score = 2000000
clicker_counter = 0

def counter():
    global score
    score += 1
    points_label.config(text=score)

def autoclicker(args):
    global clicker_counter
    if args == 1:
        pass

def clickerpurchase():
    global clicker_counter
    global score
    if score >= 1000:
        score -= 1000
        clicker_counter += 1
        points_label.config(text=score)
        clicker_label['text'] += str(clicker_counter)
        clicker_label.config(text='purchase clicker(1k): ' + str(clicker_counter))

clicker_button = Button(root, text='purchase', command=lambda:[clickerpurchase, autoclicker(1)])
clicker_button.grid(row=0, column=3)

clicker_label = Label(root, text='purchase clicker(1k): ')
clicker_label.grid(row=0, column=2)

points_label = Label(root, text='0')
points_label.grid(row=0, column=1)

points_button = Button(root, text='click me', command=counter)
points_button.grid(row=0, column=0)

points_label.config(text=score)
root.mainloop()

The clicker_button is the main concern. The clickerpurchase() function is in charge of updating the score and clicker_counter. The button is also tied to autoclicker(args). I want the clicker_button to click the points_button every once in a while. I was thinking of putting the auto clicking code in the autoclicker(args) function, but I don't know the code for it.

EDIT: I made a 'while' loop in my counter() function and added args to it. I gave points_button an arg of 1 and clicker_button an arg of 2. My code now looks like this:

def counter(args):
    global score
    if args == 1:
        score += 1
        points_label.config(text=score)
    if args == 2:
        while args == 2:
            time.sleep(1)
            points_button.invoke()

points_button = Button(root, text='click me', command=counter(1))
points_button.grid(row=0, column=0)

clicker_button = Button(root, text='purchase', command=lambda:[clickerpurchase, counter(2)])
clicker_button.grid(row=0, column=3)

Whenever I click the clicker_button the points_button gets clicked, but the program crashes. I completely discarded the autoclicker(args) function.


Solution

  • As far as your function is concerned, you could try something like this

    def autoclicker(args):
        global clicker_counter
        if args == 1:
            time_interval=1000 #change it as you like
            points_button.invoke()
            root.after(time_interval,lambda:autoclicker(1))
    

    I have used the root.after() method and this will invoke your points_button every time_interval milliseconds you specify.

    Also, by what I have understood your aim is (please feel free to correct me on this), you don't really need a button to increase the score in the first place, you can just replace the points_button.invoke() in the code with counter() and it should give the same result. Even if you plan to have multiple of these, you can maybe pass on a different arguments to clickerpurchase(), counter(), autoclicker(args) to have different scores for each item.

    EDIT (after question edit)

    time.sleep() in an infinite loop will not work as the entire program will wait for that to be complete before it can execute any other thing, and so it stops responding and crashes. Try to use the .after() method in a similar way as I have mentioned above.

    And if you want to work without the autoclicker() function as you said in the edit, you can make the following changes

    def counter(args):
        global score
        if args==1:
            score += 1
            points_label.config(text=score)
        elif args==2:
            time_interval=1000 #change it as you like
            points_button.invoke()
            root.after(time_interval,lambda:counter(2))
    
    points_button = Button(root, text='click me', command=lambda:counter(1))