How do you create a Button on a tkinter Canvas?

The Tkinter pack manager tries to resize the parent widget to the correct size to contain its child widgets, and no larger, by default. So the canvas is there - but it's precisely the same size as the button, and thus invisible.

If you want to place a widget on a canvas without causing the canvas to dynamically resize, you want the Canvas.create_window() function:

# ... snip ...
button1 = Button(self, text = "Quit", command = self.quit, anchor = W)
button1.configure(width = 10, activebackground = "#33B5E5", relief = FLAT)
button1_window = canvas1.create_window(10, 10, anchor=NW, window=button1)

This will create your button with upper-left corner at (10, 10) relative to the canvas, without resizing the canvas itself.

Note that you could replace the window argument with a reference to any other Tkinter widget. One caveat, though: the named widget must be a child of the top-level window that contains the canvas, or a child of some widget located in the same top-level window.


you can use button1.place(x=0,y=0) geometry manager instead of pack(side =TOP) pack resize the master widget to makes it large enough to hold the child widget

http://effbot.org/tkinterbook/pack.htm#Tkinter.Pack.pack_propagate-method

http://effbot.org/tkinterbook/place.htm


I had the exact same problem. There isn't an official way that I know, but here's a way around it:

from Tkinter import *
root = Tk()
def clicked(event):
    print("pressed")
canvas1 = Canvas(root, relief = FLAT, background = "#D2D2D2")
canvas1.pack()
buttonBG = canvas1.create_rectangle(0, 0, 100, 30, fill="grey40", outline="grey60")
buttonTXT = canvas1.create_text(50, 15, text="click")
canvas1.tag_bind(buttonBG, "<Button-1>", clicked) ## when the square is clicked runs function "clicked".
canvas1.tag_bind(buttonTXT, "<Button-1>", clicked) ## same, but for the text.
root.mainloop()