How can I pack up multiple functions in a single widget?

Viewed 96

I want to pack some func. in a single widget so that I can interact with that particular widget using bind func.

There's Frame widget which packs up widgets in it and canvas.create_window func. in Canvas widget which also does the same as Frame.

Following program generates sticman after every 3 sec. And when user click the stickman, it disappears.

I tried using Frame to pack functions ...

    from Tkinter import *
    root = Tk()
    
    hitbox = Frame(root, height = 100, width= 100)
    hitbox.pack()
    can = Canvas(hitbox, height= 450, width= 1000)   # Canvas inside hitbox
    can.pack()

    def stickman (a,b,c,d):
        # Code that makes stickman according to coordinates

    def HP(p,q):
        # Code that makes Progressbar widget inside hitbox which act as healthbar
    
    counter = 0
    def init():
        if counter == 10:
            pass
        else:
            counter +=1
            stickman(100,100,130,130)
            HP(90, 120)
            root.after(3000, init)    # Stickman respawns after 3 seconds

    def kill():
        hitbox.destroy()

    hitbox.bind('<Button-1>', kill)
    root.mainloop()

Stickman respawns after every 3 seconds but bind func. with frame does not seems to be working when running code. Stickman doesn't disappears when clicked.

1 Answers

I think what you are asking for is to destroy the Tkinter frame when Button 1 or the left button on the mouse is clicked. The stickman doesn't disappear because the frame isn't actively listening for the key click unlike a label or an entry field would do. So, there are 2 easy fixes for this problem:

1. Binding to Root Window

Binding the keybind to the root window would solve the problem mostly because the root window is always actively listening for keybinds unlike the frame or an input field. The only problem with this approach is that the user can click anywhere on the window to destroy the frame.

2. Binding to the Stickman Itself

Binding the keybind to the stickman itself is the cleanest approach because it would be just the same as the first solution but this time the user can only click on the stickman to destroy the frame. This is probably the solution you were looking for. To implement this solution just replace the root.bind('<Button-1>', kill) with stickman.bind('<Button-1>', kill) (or whatever the name is of your stickman is) after defining the stickman but before packing it.


I atatched a modified version of your code down below for the first option:

from tkinter import *
root = Tk()

def kill(event=None):
    hitbox.destroy()

root.bind('<Button-1>', kill)
hitbox = Frame(root, height = 100, width= 100)
hitbox.pack()
can = Canvas(hitbox, height= 450, width= 1000)   # Canvas inside hitbox
can.pack()

def stickman (a,b,c,d):
    pass
    # Code that makes stickman according to coordinates

def HP(p,q):
    pass
    # Code that makes Progressbar widget inside hitbox which act as healthbar

counter = 0
def init():
    if counter == 10:
        pass
    else:
        counter +=1
        stickman(100,100,130,130)
        HP(90, 120)
        root.after(3000, init)    # Stickman respawns after 3 seconds

root.mainloop()
Related