Tkinter 可滚动和可扩展的 PanedWindow [英] Tkinter Scrollable and expandable PanedWindow

查看:36
本文介绍了Tkinter 可滚动和可扩展的 PanedWindow的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在 Stackoverflow 上搜索了很多,还有很多博客、文档……但我没有找到制作PanedWindow"的方法;可滚动和展开 + 填充.

I already searched a lot on Stackoverflow, and a lot of blogs, docs... And I don't find the way to make a "PanedWindow" to be scrollable AND expand + fill.

检查这个例子

"""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 类中有注释

There is a comment in the ScrollableFrame class

  • 评论 frame.pack() =>它滚动,但内容未展开且未填充 X

  • comment the frame.pack() => it scrolls, but the content is not expanded and doesn't fill X

取消注释 frame.pack() =>现在内容填满了空间,但它不可滚动

uncomment the frame.pack() => now the content fill the space, but it's not scrollable

我想做的只是让内容填满空间"并且是可滚动的".

What I want to do is simply to make the content "fill the space" and to be "scrollable".

如果您发现了问题,并且您可以解决它(或提供解决方案)...谢谢!

If you find the problem, and if you can fix it (or provide a solution)... thanks !

推荐答案

默认情况下,内部框架将扩展或收缩到其内容的最佳大小.由于框架的内容没有画布那么宽,所以框架不会和画布一样宽.

By default, the inner frame will expand or shrink to the optimal size for its contents. Since the contents of the frame aren't as wide as the canvas, the frame will not be as wide as the canvas.

如果你想让它填满画布,你需要明确地将宽度设置为在画布改变大小时与画布的宽度相同.

If you want it to fill the canvas, you need to explicitly set the width to be the same as the width of the canvas whenever the canvas changes size.

首先,让我们确保我们可以通过给它一个标签来识别内部框架.您可以同样轻松地捕获 window_create 返回的标识符.

First, let's make sure we can identify the inner frame by giving it a tag. You could just as easily capture the identifier returned by window_create.

canvas.create_window((0, 0), window=frame, anchor=CENTER, tags=("inner_frame",))

接下来,添加一个绑定以在画布配置更改时调用函数.

Next, add a binding to call a function whenever the canvas configuration changes.

canvas.bind("<Configure>", self.resize_inner_frame)

最后,定义resize函数.在 事件上,event 对象将包含一个 width 参数,该参数表示对象的宽度.我们可以用这个来确定内框的宽度.

Finally, define the resize function. On <Configure> events, the event object will contain a width parameter which represents the width of the object. We can use this to determine the width of the inner frame.

def resize_inner_frame(self, event):
    self.canvas.itemconfigure("inner_frame", width=event.width)

您可能需要调整宽度以适应画布边框.

You might need to adjust the width to accommodate canvas borders.

这篇关于Tkinter 可滚动和可扩展的 PanedWindow的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆