9

I want to obtain a button out of a Canvas. I've tried to pack the canvas in the button widget, but that didn't work. Googling a bit, I've found (here: How do you create a Button on a tkinter Canvas?) that the Canvas method create_window might help. But there should be something wrong in the way I'm using it.

import Tkinter

DIM = 100

root = Tkinter.Tk()
frame = Tkinter.Frame(root)

button = Tkinter.Button(None, width=DIM, height=DIM, command=root.quit)

circle = Tkinter.Canvas(frame, width=DIM, height=DIM)
circle.create_oval(5, 5, DIM-5, DIM-5, fill="red")
circle.create_window(0, 0, window=button)

frame.grid()
circle.grid(row=1, column=1)

root.mainloop()

If I erase the create_window line, I can se my painting but I can't (obviously) click on it. But in this way, the button widget cover my circle and shows a sad empty button.

Basically, I want to create a button with a red circle painted inside.

4

2 回答 2

15

Tkinter 不允许您直接在画布以外的小部件上绘图,并且画布绘图将始终位于嵌入式小部件下方。

简单的解决方案是仅使用画布创建按钮效果。这样做并没有什么特别之处:只需创建一个画布,然后为 ButtonPress 和 ButtonRelease 添加绑定以模拟按下的按钮。

这是一个粗略的想法:

class CustomButton(tk.Canvas):
    def __init__(self, parent, width, height, color, command=None):
        tk.Canvas.__init__(self, parent, borderwidth=1, 
            relief="raised", highlightthickness=0)
        self.command = command

        padding = 4
        id = self.create_oval((padding,padding,
            width+padding, height+padding), outline=color, fill=color)
        (x0,y0,x1,y1)  = self.bbox("all")
        width = (x1-x0) + padding
        height = (y1-y0) + padding
        self.configure(width=width, height=height)
        self.bind("<ButtonPress-1>", self._on_press)
        self.bind("<ButtonRelease-1>", self._on_release)

    def _on_press(self, event):
        self.configure(relief="sunken")

    def _on_release(self, event):
        self.configure(relief="raised")
        if self.command is not None:
            self.command()

要完成这种错觉,您需要在<Enter>and上设置绑定<Leave>(以模拟活动状态),并确保在按钮释放时光标位于按钮上方 - 请注意,如果您在释放之前将鼠标移开。

于 2013-10-14T22:00:15.610 回答
5

您可以做的是将画布绑定到鼠标:

import Tkinter

DIM = 100

root = Tkinter.Tk()
frame = Tkinter.Frame(root)

circle = Tkinter.Canvas(frame)
circle.create_oval(5, 5, DIM-5, DIM-5, fill="red")

frame.grid()
circle.grid(row=1, column=1)

##################################
def click(event):
    root.quit()

circle.bind("<Button-1>", click)
##################################

root.mainloop()

现在,如果用户在画布内单击,click将调用函数(本质上,画布现在已成为一个按钮)。

请注意,如果用户单击画布中的任何位置click,则会调用该函数。如果你想让它只在用户点击圆圈时调用,你可以使用and来获取点击的坐标。一旦你有了这些,你可以运行一个计算来确定这些坐标是否在圆内。 是一个参考。clickevent.xevent.yxy

于 2013-10-14T21:42:03.010 回答