#python-3.x #tkinter
Вопрос:
Я уже много искал в Stackoverflow и во многих блогах, документах… И я не нахожу способа сделать «Панорамное окно» доступным для прокрутки И расширения заливки.
Проверьте этот пример
"""Test"""
# pylint: disable=unused-wildcard-import,wildcard-import
from tkinter import Canvas, Scrollbar, Tk, Wm
from tkinter.constants import BOTH, CENTER, HORIZONTAL, LEFT, NSEW, X
from tkinter.ttk import Button, Frame, Label, PanedWindow, Style
STYLE = {
"TButton": {
"configure": {
"background": "#333333",
"foreground": "white",
"padding": 8,
"relief": "flat",
"border": 2,
},
"map": {
"background": [("active", "#777777")],
"foreground": [("active", "white")],
},
},
}
class ScrollableFrame(Frame):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
scrollbar = Scrollbar(self, orient="vertical")
scrollbar.pack(side="right", fill="y")
canvas = Canvas(self, borderwidth=2, background="red")
canvas.pack(side=LEFT, fill=BOTH, expand=True)
canvas.configure(yscrollcommand=scrollbar.set)
scrollbar.configure(command=canvas.yview)
frame = Frame(canvas, style="DEBUG.TFrame")
canvas.create_window((0, 0), window=frame, anchor=CENTER)
# COMMENT THIS, and the paned is scrollable, but frame does NOT expand
# frame.pack(expand=1, fill=BOTH)
frame.bind("<Configure>", self.on_configure)
self.scollbar = scrollbar
self.canvas = canvas
self.frame = frame
def on_configure(self, event):
self.canvas.configure(
scrollregion=self.canvas.bbox("all"),
)
def create_right_pane(master):
frame = Frame(master)
label = Label(frame, text="This is a cool text")
label.pack()
return frame
def create_left_pane(master):
frame = ScrollableFrame(master)
title = Label(frame.frame, text="Hello !!!")
title.pack(expand=True, fill=BOTH, anchor=CENTER)
for i in range(100):
Button(frame.frame, text=f"Channel {i} ❱").pack(expand=True, fill=BOTH)
return frame
app = Tk(className="MyApp")
style = Style()
style.theme_create("app", None, STYLE)
style.theme_use("app")
app.title("MyApp")
app.geometry("1120x550")
splitpane = PanedWindow(app, orient=HORIZONTAL)
splitpane.pack(expand=True, fill=BOTH)
leftframe = create_left_pane(splitpane)
rightframe = create_right_pane(splitpane)
splitpane.add(leftframe, weight=1)
splitpane.add(rightframe, weight=5)
app.mainloop()
В классе ScrollableFrame есть комментарий
- прокомментируйте фрейм.pack() => он прокручивается, но содержимое не расширяется и не заполняет X
- раскомментируйте фрейм.pack() => теперь содержимое заполняет пространство, но его нельзя прокручивать
То, что я хочу сделать, — это просто сделать содержимое «заполняющим пространство» и «прокручиваемым».
Если вы обнаружите проблему и сможете ее устранить (или предоставить решение)… Спасибо!
Ответ №1:
По умолчанию внутренняя рамка будет расширяться или сжиматься до оптимального размера для ее содержимого. Поскольку содержимое рамки не такое широкое, как холст, рамка не будет такой широкой, как холст.
Если вы хотите, чтобы он заполнял холст, вам нужно явно задать ширину, равную ширине холста, всякий раз, когда холст меняет размер.
Во-первых, давайте убедимся, что мы можем идентифицировать внутреннюю рамку, присвоив ей метку. Вы могли бы так же легко захватить идентификатор, возвращенный window_create
.
canvas.create_window((0, 0), window=frame, anchor=CENTER, tags=("inner_frame",))
Затем добавьте привязку для вызова функции при каждом изменении конфигурации холста.
canvas.bind("<Configure>", self.resize_inner_frame)
Наконец, определите функцию изменения размера. В <Configure>
случае событий event
объект будет содержать width
параметр, представляющий ширину объекта. Мы можем использовать это для определения ширины внутренней рамки.
def resize_inner_frame(self, event):
self.canvas.itemconfigure("inner_frame", width=event.width)
Возможно, вам потребуется настроить ширину для размещения границ холста.
Комментарии:
1. Ты мой герой ! Есть небольшая последняя проблема, которую я решу при запуске, сайзер плохо расположен, а холст не подходит к рамке. Мне нужно «обновить» представление (изменить размер или переместить размер), но решение абсолютно классное. Большое спасибо.
2. Обратите внимание, что границы и цвет bg были здесь для отладки, я удалил их, и все в порядке
3. Исправлено путем добавления вызова «on_configure» из метода «resize_inner_frame»;)