#python #tkinter
#python #tkinter
Вопрос:
Я использую tk.Canvas .create_window
для размещения кнопок на моем canvas, чтобы обеспечить эффект «прокрутки», при котором я могу перемещаться по списку кнопок: пример
Как видно на gif, справа есть полоса прокрутки, которая позволяет прокручивать холст по вертикали, а созданные на холсте окна кнопок можно циклически просматривать. Однако, как видно, кнопки перекрывают полосу прокрутки. Возможно ли настроить отображение окон только в виджете canvas? Изменение шаблона кнопки не имеет эффекта:
button = tk.Button(self, image=self.data[i].image, anchor='nw', width=400, height=72, highlightthickness=0, bd=0, relief='flat', bg='#dfdbda', compound='left', text="thing", fg='black', font='System, 10')
buttonwindow = self.canvas.create_window(5, 10, anchor='nw', window=button)
Независимо от того, какие параметры конфигурации заданы, окно по-прежнему появляется из виджета canvas. Почему он это делает? Есть ли лучшая альтернатива create_window, где я могу поместить кнопки в виджет canvas?
Комментарии:
1. Проблема, похоже, не в кнопках, а в полосе прокрутки. Вы помещаете полосу прокрутки в холст, что приводит к ее перезаписи объектами canvas. Просто создайте его как виджет рядом с canvas (плюс один столбец, если вы используете grid), и он больше не будет перекрываться.
Ответ №1:
Решение простое: не помещайте полосу прокрутки внутри холста. Используйте тот же шаблон для полосы прокрутки, что и для холста. Кроме того, кнопки должны быть дочерними элементами canvas.
Поскольку вы не предоставили достаточно кода для создания рабочего примера, вот надуманный пример:
import tkinter as tk
class ButtonScroller(tk.Frame):
def __init__(self, parent, **kwargs):
super().__init__(parent, **kwargs)
self.canvas = tk.Canvas(self, bg="lightgray", bd=2, relief="groove")
self.vsb = tk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.vsb.set)
self.vsb.pack(side="right", fill="y")
self.canvas.pack(side="left", fill="both", expand=True)
self.buttons = []
self.data = []
@property
def count(self):
return len(self.buttons)
def add_button(self, image, text):
bbox = self.canvas.bbox("all") or (0,0,0,0)
x, y = 4, bbox[3] 5
# use a fake image to keep the example simple...
self.data.append(image)
button = tk.Button(self.canvas, image=image, anchor='nw', width=400, height=72,
highlightthickness=0, bd=0, relief='flat', bg='#dfdbda',
compound='left', text=text, fg='black', font='System, 10')
self.buttons.append(button)
self.canvas.create_window(x, y, anchor="nw", window=button)
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def add_button():
# create a dummy image to simplify this example
image = tk.PhotoImage(width=64, height=64)
n = buttonframe.count 1
text = f"Button #{n}"
buttonframe.add_button(image, text)
root = tk.Tk()
buttonframe = ButtonScroller(root, bd=1, relief="raised")
toolbar = tk.Frame(root)
toolbar.pack(side="top", fill="x")
buttonframe.pack(side="top", fill="both", expand=True)
add_button = tk.Button(toolbar, text="Add", command=add_button)
add_button.pack(side="left", padx=2, pady=2)
root.mainloop()
Комментарии:
1. Полоса прокрутки находится не внутри canvas, они оба помещены в один фрейм.
2. @xerp152: другая проблема заключается в том, что кнопки должны быть дочерними элементами canvas, что является частью этого ответа.
Ответ №2:
Решение, которое я нашел (полоса прокрутки никогда не была внутри canvas): я поместил набор основных кнопок на canvas, что ограничило их исключительно этим виджетом.