Reputation: 757
I have nice polygon I drew in a Tkinter canvas. I would like put that as the icon of a Tkinter button.
I see in this how to put a button on a canvas, but that covers up the polygon. And of course, if I put the polygon over the button, the button is not accessible.
I am trying to avoid using an external image. I'd like to keep the code self-contained and not be dependent on the path to an image. Things will be break if we ever move the code.
from Tkinter import *
class Example(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.widget()
def Xshape (self,canvas,x,y,p,t,outline='black',fill='green',width=1):
points = []
s = t - p
for i in (1,-1):
points.extend(( x, y + (i*p) ))
points.extend(( x + (i*s), y + (i*t) ))
points.extend(( x + (i*t), y + (i*s) ))
points.extend(( x + (i*p), y))
points.extend(( x + (i*t), y - (i*s) ))
points.extend(( x + (i*s), y - (i*t) ))
canvas.create_polygon(points,outline=outline,
fill=fill,width=width)
def widget(self):
cWidth=64.
cHeight=64.
self.canv = Canvas(frame,width=cWidth,height=cHeight)
self.Xshape(self.canv, (cWidth+2)/2,(cHeight+2)/2, cHeight/5,cHeight/2)
self.toggle = Button(frame,relief=FLAT,text='test')
self.win = self.canv.create_window(cWidth/2,cHeight/2,anchor=CENTER,window=self.toggle)
self.canv.grid(row=0,column=2)
root = Tk()
root.geometry('100x100+10+50')
root.wm_title("Telescope Health Status")
root.grid_rowconfigure( 1, weight=1)
root.grid_columnconfigure( 0, weight=1)
frame = Frame(root,bg='light blue',padx=30)
frame.grid(row=0, column=0, columnspan=20, sticky='ew')
app = Example(root)
app.mainloop()
This only puts a button over the polygon. I want to put the polygon inside the button.
Upvotes: 1
Views: 254
Reputation: 16169
Instead of putting your canvas in a button, you can make the canvas itself emulates a button's behavior by using bindings on Enter, Leave and mouse events:
The Canvas relief is set to "raised" with a borderwidth of 1 to make it look like a button
The background color is changed into a lighter grey when the cursor enters the Canvas
The relief is set to "sunken" when the mouse button 1 is pressed
The command given in argument is executed when button 1 is released but only if the cursor is still on the Canvas and the relief is et back to "raised"
The relief is set back to "raised" and the normal background color is restored when the cursor leaves the Canvas
from Tkinter import *
class ButtonCanvas(Canvas):
def __init__(self, master=None, command=lambda: None, **kw):
Canvas.__init__(self, master, relief="raised", bd=1, **kw)
self._bg = self.cget("bg")
cWidth = 64
cHeight = 64
self.configure(width=64, height=64)
self.Xshape((cWidth+2)/2,(cHeight+2)/2, cHeight/5,cHeight/2)
self.command = command
self.bind("<Enter>", self.on_enter)
self.bind("<Leave>", self.on_leave)
self.bind("<ButtonPress-1>", self.on_b1press)
self.bind("<ButtonRelease-1>", self.on_b1release)
def on_enter(self, event):
self.configure(background="#ececec")
def on_leave(self, event):
self.configure(background=self._bg)
self.configure(relief="raised")
def on_b1press(self, event):
self.configure(relief="sunken")
def on_b1release(self, event):
self.configure(relief="raised")
if self.winfo_containing(event.x_root, event.y_root) == self:
self.command()
def Xshape (self,x,y,p,t,outline='black',fill='green',width=1):
points = []
s = t - p
for i in (1,-1):
points.extend(( x, y + (i*p) ))
points.extend(( x + (i*s), y + (i*t) ))
points.extend(( x + (i*t), y + (i*s) ))
points.extend(( x + (i*p), y))
points.extend(( x + (i*t), y - (i*s) ))
points.extend(( x + (i*s), y - (i*t) ))
self.create_polygon(points,outline=outline,
fill=fill,width=width)
root = Tk()
def cmd():
print("ok")
ButtonCanvas(root, command=cmd).pack()
Button(root, command=cmd).pack()
root.mainloop()
Upvotes: 1