Search code examples
pythonpython-3.xtkintermouseeventtkinter.checkbutton

how to create new checkbuttons with a mouse click in python


I want to create a program where the user can create different buttons with the click of the mouse, those buttons should be independent. With this logic, the user can create a checkbutton that works, change from green to red when is selected. My problem is that if the user click the mouse again, the checkbutton moves instead of creating a new checkbutton. Any suggestion how to do it?

from tkinter import *

root = Tk()

button1 = IntVar()

def color_checkbutton():  # define the colors of the checkbutton
    if button1.get() == 1:
        example_checkbutton.configure(bg='red')
    else:
        example_checkbutton.configure(bg='green')
example_checkbutton = Checkbutton(root, variable=button1, textvariable=button1, command=color_checkbutton)

def place_checkbutton_in_canvas(e):  # order to insert the checkbutton
    xx_and = e.x
    yy_and = e.y
    example_checkbutton.place(x=xx_and, y=yy_and)

root.bind('<Button-1>', place_checkbutton_in_canvas)

root.mainloop()

Solution

  • You do only have one example_checkbutton. Whenever you call the .place()method, this button is moved around.

    If you want new ones, just create them as new Checkbox-widgets:

    def place_checkbutton_in_canvas(e):  # order to insert the checkbutton
        if len(str(e.widget))<3: ## Don't place a new one if a checkbox was clicked
            xx_and = e.x
            yy_and = e.y
            Checkbutton(root, variable=button1, textvariable=button1, command=color_checkbutton).place(x=xx_and, y=yy_and)
    
    

    This creates new checkbuttons which are all linked to the button1 variable.

    EDIT:

    If you want new checkbuttons, you'll have to maintain a list of IntVar() and Checkbutton() objects which is getting longer with each click. The code below should work. I also execute the color change upon creation to create them green and red.

    from tkinter import *
    
    root = Tk()
    
    buttons = []
    
    class CMD: #Auxilliary function for callbacks using parameters. Syntax: CMD(function, argument1, argument2, ...)
        def __init__(s1, func, *args):
            s1.func = func
            s1.args = args
        def __call__(s1, *args):
            args = s1.args+args
            s1.func(*args)
    
    def color_checkbutton(pos=0):  # define the colors of the checkbutton
        if buttons[pos][0].get() == 1:
            buttons[pos][2].configure(bg='red')
        else:
            buttons[pos][2].configure(bg='green')
    
    def place_checkbutton_in_canvas(e):  # order to insert the checkbutton
        if len(str(e.widget))<3: ## Don't place a new one if a checkbox was clicked
            b = IntVar()
            pos = len(buttons)
            xx_and = e.x
            yy_and = e.y
            buttons.append([b,pos, Checkbutton(root, variable=b, textvariable=b, command=CMD(color_checkbutton,pos))])
            buttons[-1][2].place(x=xx_and, y=yy_and)
            color_checkbutton(pos)
    
    root.bind('<Button-1>', place_checkbutton_in_canvas)
    
    root.mainloop()