【问题标题】:Scrollable frame does not fill canvas可滚动框架不填满画布
【发布时间】:2018-07-13 21:09:16
【问题描述】:

我使用 Python 2.7,并且我有一个可滚动的框架,其中画布不会缩小以适合我想要使其可滚动的框架。

我查看了这个问题的答案,但运行它时它不起作用: How to resize a scrollable frame to fill the canvas?

当我在画布内打印框架的宽度时,它显示为 0。

我还在我的电脑上运行了这个问题的答案中的代码: Scrollable Frame does not resize properly using tkinter in Python 但它仍然会在标签左侧显示白色画布,并且在删除标签时不会调整大小。

看起来像这样:

这是我的代码,基于这个问题的答案: Adding a scrollbar to a group of widgets in Tkinter

from Tkinter import *

class Scrollable_frame(Frame):

    def __init__(self, parent, title, values):

        self.parent = parent

        Frame.__init__(self, self.parent)

        self.canvas = Canvas(self, borderwidth=0, background="#ffffff")
        self.scrollbar = Scrollbar(self, command=self.canvas.yview)
        self.innerFrame = Radiobutton_frame(self.canvas,title,values)

        self.canvas.configure(yscrollcommand=self.scrollbar.set)

        self.canvas.grid(row=0, column=0, sticky= N+S)
        self.scrollbar.grid(row=0, column=1, sticky = N+S)
        self.canvas.create_window((0,0),window = self.innerFrame,anchor="nw")

        self.innerFrame.bind("<Configure>", self.set_canvas_scrollregion)

        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)


    def set_canvas_scrollregion(self, event):

        width = event.width - 4
        self.canvas.itemconfigure("self.innerFrame ", width=width)
        self.canvas.config(scrollregion=self.canvas.bbox("all"))


class Radiobutton_frame(LabelFrame):

    def __init__(self, parent, title, values):

        """            
        In: parent - Canvas
            title - String
            values - List of Int
        """

        self.radiobuttons = {}
        self.parent = parent

        self.selection = StringVar()
        self.selection.set("init")

        LabelFrame.__init__(self, self.parent, text = title)

        for value in values:
            self.add_radiobutton(value)


    def add_radiobutton(self, value):

        """
        Adds a radiobutton to the frame.

        In: item - String
        """

        # Associate to same variable to make them function as a group
        self.radiobuttons[value] = Radiobutton(master = self,
                                                variable = self.selection,
                                                text = value,
                                                value = value)
        self.radiobuttons[value].pack(anchor=W)

# Usage example

root = Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
scrollableFrame = Scrollable_frame(root, "Canvas not resizing", range(30))
scrollableFrame.grid(row=0, column=0, sticky=N+S+E+W)

if __name__ == '__main__':
    root.mainloop()

【问题讨论】:

  • 你能提供一张你想要的图片吗?
  • 您说您尝试了在画布的&lt;Configure&gt; 事件上绑定的建议,但没有成功。这就是解决方案,那么您能否展示您的尝试并解释“不起作用”是什么意思?

标签: python tkinter scrollbar tkinter-canvas


【解决方案1】:

我认为上述问题的代码 sn-p 不适合 a Minimal, Complete, and Verifiable example,但至少它是可运行的。


How to resize a scrollable frame to fill the canvas?相比,你犯了三个错误

其中最重要的是,在链接的问题中,OP 使用选项 tags 而您不使用。替换:

self.canvas.create_window((0,0),window = self.innerFrame,anchor="nw")

与:

self.canvas.create_window((0,0),window = self.innerFrame, anchor="nw", tags="my_tag")

另一个错误是您绑定了框架调整大小的事件,而不是实际的 Canvas 调整大小,Bryan's comment here 中也指出了这一点。替换:

self.innerFrame.bind("<Configure>", self.set_canvas_scrollregion)

与:

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

最后,tkinter 似乎不接受带标签的空格字符,替换:

self.canvas.itemconfigure("self.innerFrame ", width=width)

与:

self.canvas.itemconfigure("my_tag", width=width)

最后,你应该有:

from Tkinter import *

class Scrollable_frame(Frame):

    def __init__(self, parent, title, values):

        self.parent = parent

        Frame.__init__(self, self.parent)

        self.canvas = Canvas(self, borderwidth=0, background="#ffffff")
        self.scrollbar = Scrollbar(self, command=self.canvas.yview)
        self.innerFrame = Radiobutton_frame(self.canvas,title,values)

        self.canvas.configure(yscrollcommand=self.scrollbar.set)

        self.canvas.grid(row=0, column=0, sticky= N+S)
        self.scrollbar.grid(row=0, column=1, sticky = N+S)
        self.canvas.create_window((0,0),window = self.innerFrame,anchor="nw",
                                                                tags="my_tag")

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

        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)


    def set_canvas_scrollregion(self, event):

        width = event.width - 4
        self.canvas.itemconfigure("my_tag", width=width)
        self.canvas.config(scrollregion=self.canvas.bbox("all"))


class Radiobutton_frame(LabelFrame):

    def __init__(self, parent, title, values):

        """            
        In: parent - Canvas
            title - String
            values - List of Int
        """

        self.radiobuttons = {}
        self.parent = parent

        self.selection = StringVar()
        self.selection.set("init")

        LabelFrame.__init__(self, self.parent, text = title)

        for value in values:
            self.add_radiobutton(value)


    def add_radiobutton(self, value):

        """
        Adds a radiobutton to the frame.

        In: item - String
        """

        # Associate to same variable to make them function as a group
        self.radiobuttons[value] = Radiobutton(master = self,
                                                variable = self.selection,
                                                text = value,
                                                value = value)
        self.radiobuttons[value].pack(anchor=W)

# Usage example

root = Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
scrollableFrame = Scrollable_frame(root, "Canvas not resizing", range(30))
scrollableFrame.grid(row=0, column=0, sticky=N+S+E+W)

if __name__ == '__main__':
    root.mainloop()

【讨论】:

  • 非常感谢您的帮助,感谢您花费时间和精力帮助我。实际上,我希望画布缩小到内框大小,而不是内框展开以填充画布。这不是问题,因为我可以将画布的大小硬编码为大约内部框架的大小。令我惊讶的是,在画布上绘制后,打印语句告诉我内框为 0,也许有人知道为什么?再次感谢 Nae。
  • 也许可以在画布上尝试width=self.innerFrame.winfo_reqwidth()
  • 我试过了,但不幸的是画布缩小到框架宽度以下,所以框架什么也没显示。我仍然可以移动滚动条。
猜你喜欢
  • 1970-01-01
  • 2015-04-18
  • 1970-01-01
  • 2018-01-16
  • 1970-01-01
  • 1970-01-01
  • 2021-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多