Как сделать кнопку с помощью виджета Tkinter Canvas?
Я хочу получить кнопку из холста. Я пытался pack
холст в виджете кнопки, но это не сработало. Немного погуглив, я нашел (здесь: как вы создаете кнопку на холсте tkinter?), что метод Canvas create_window
может помочь. Но должно быть что-то не так в том, как я его использую.
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()
если я сотру create_window
line, я могу видеть свою картину, но я не могу (очевидно) нажать на нее. Но таким образом, виджет кнопки покрывает мой круг и показывает грустную пустую кнопку.
в принципе, я хочу создать кнопку с красным кружком внутри расписана.
2 ответов
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>
и <Leave>
(для имитации активного состояния), а также убедитесь, что курсор находится над кнопкой на кнопке release -- обратите внимание, как реальные кнопки ничего не делают, если вы переместите мышь, прежде чем отпустить.
что вы можете сделать, это связать полотно для мыши:
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
будет вызываться, если пользователь нажмет в любом месте в холст. Если вы хотите сделать это так, что click
только вызывается, когда пользователь щелкает по кругу, вы можете использовать event.x
и event.y
, чтобы получить x
и y
координаты мыши. Как только они у вас есть, вы можете запустить расчет, чтобы определить, находятся ли эти координаты в пределах круга. здесь ссылка на это.