Проблема
Используя tkinter в Python, я пытаюсь создать пользовательские кнопки и другие виджеты, расширяя виджет Canvas .Как я могу изменить, какие пользовательские виджеты холста рисуются сверху, когда пользователь взаимодействует с ними?
lift () работает для обычных кнопок tkinter и других виджетов, но выдает ошибку при попыткеиспользовать его для поднятия Canvas, потому что Canvas имеет свой собственный метод lift () .Лифт Canvas не поддерживается для Canvas в пользу tag_raise ().Тем не менее, документация tag_raise () говорит, что это «не работает с элементами окна», что соответствует моему опыту, и указывает мне использовать вместо этого lift ().Мой мозг гнался за этой, казалось бы, круглой документацией, пока не вызвал своеобразное исключение StackOverflow, которое заставляет меня спросить вас.
Иллюстрация кода
Вот некоторый основной код, который работает и иллюстрирует мою проблему.Я включил button3, обычную кнопку, которая может поднимать (), как и ожидалось.Однако, если я нажимаю на custom_button1, обработчик click_handler вызывает исключение.
from tkinter import Button, Canvas, Frame, Tk
from tkinter.constants import NW
class Example(Frame):
def __init__(self, root):
Frame.__init__(self, root)
self.canvas = Canvas(self, width=200, height=200, background="black")
self.canvas.grid(row=0, column=0, sticky="nsew")
self.button3 = Button(self.canvas, text="button3")
self.custom_button1 = MyCustomButton(self.canvas)
self.custom_button2 = MyCustomButton(self.canvas)
self.canvas.create_window(20, 20, anchor=NW, window=self.button3)
self.canvas.create_window(40, 40, anchor=NW, window=self.custom_button1)
self.canvas.create_window(34, 34, anchor=NW, window=self.custom_button2)
self.button3.bind("<Button-1>", self.click_handler)
self.custom_button1.bind("<Button-1>", self.click_handler)
self.custom_button2.bind("<Button-1>", self.click_handler)
def click_handler(self,event):
event.widget.lift() #raises exception if event.widget is a MyCustomButton
#note that Canvas.lift() is deprecated, but documentation
#says Canvas.tag_raise() doesn't work with window items
class MyCustomButton(Canvas):
def __init__(self, master):
super().__init__(master, width=40, height=25, background='blue')
if __name__ == "__main__":
root = Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
Это работает так, как требуется для button3, но для custom_button1 возникает исключение:
_tkinter.TclError: wrong # args: should be ".!example.!canvas.!mycustombutton2 raise tagOrId ?aboveThis?"
Это исключение имеет смысл в том контексте, что Canvas.lift () и Canvas.tag_raise () обычно используются для воздействия на элемент холста по тегу или идентификатору, а не на сам холст.Я просто не знаю, что делать с изменением порядка стека самого холста, чтобы я мог использовать его в качестве собственного виджета.
Обходной путь, который я рассмотрел
Я мог быуправляйте связкой пользовательских виджетов на холсте, имея только один холст, который обрабатывает все рисунок и все события мыши для все виджеты.У меня все еще могут быть классы для виджетов, но вместо наследования от Canvas они будут принимать параметры Canvas.Поэтому добавление будет выглядеть примерно так, как показано ниже, и мне придется написать аналогичный код для подъема, перемещения, определения, применено ли к этой кнопке событие щелчка, изменение активного состояния и т. Д.
def add_to_canvas(self, canvas, offset_x=0, offset_y=0):
self.button_border = canvas.create_rectangle(
offset_x + 0, offset_y + 0,
offset_x + 40, offset_y + 25
)
#create additional button features
Этот обходной путь, кажется, идет вразрез с установленными парадигмами кодирования в tkinter.Кроме того, я считаю, что такой подход не позволит мне рисовать эти пользовательские кнопки над другими объектами окна.(Согласно документации create_window () «Вы не можете рисовать другие элементы холста поверх виджета.» В этом обходном пути все пользовательские кнопки будут элементами холста, и поэтому, если я читаюэто правильно, не может быть нарисовано поверх других виджетов.) Не говоря уже о дополнительном коде, который потребуется для реализации.Тем не менее, у меня нет лучшего представления о том, как это реализовать.
Заранее благодарю за помощь!