Python Tkinter 可滚动框架类?

标签 python tkinter scrollbar tkinter-canvas

我想创建一个基于the answer hereTkinter ,这是一个Frame,可以根据需要自动显示/隐藏内容周围的Scrollbar

我上面链接的答案非常适合我的需求,但需要注意的是,因为它不包含在 class 中,所以它不可重用。我认为这会非常快速和简单,但由于某种原因,一旦我将代码重构为自己的,我的AutoScrollbar就永远不会出现,无论多少Frame 的内容因窗口大小调整而被隐藏。

# This class is unchanged from the other answer that I linked to,
# but I'll reproduce its source code below for convenience.
from autoScrollbar import AutoScrollbar
from Tkinter       import Button, Canvas, Frame, HORIZONTAL, Tk, VERTICAL

# This is the class I made - something isn't right with it.
class AutoScrollable(Frame):
    def __init__(self, top, *args, **kwargs):
        Frame.__init__(self, top, *args, **kwargs)

        hscrollbar = AutoScrollbar(self, orient = HORIZONTAL)
        hscrollbar.grid(row = 1, column = 0, sticky = 'ew')

        vscrollbar = AutoScrollbar(self, orient = VERTICAL)
        vscrollbar.grid(row = 0, column = 1, sticky = 'ns')

        canvas = Canvas(self, xscrollcommand = hscrollbar.set,
                              yscrollcommand = vscrollbar.set)
        canvas.grid(row = 0, column = 0, sticky = 'nsew')

        hscrollbar.config(command = canvas.xview)
        vscrollbar.config(command = canvas.yview)

        # Make the canvas expandable
        self.grid_rowconfigure(0, weight = 1)
        self.grid_columnconfigure(0, weight = 1)

        # Create the canvas contents
        self.frame = Frame(canvas)
        self.frame.rowconfigure(1, weight = 1)
        self.frame.columnconfigure(1, weight = 1)

        canvas.create_window(0, 0, window = self.frame, anchor = 'nw')
        canvas.config(scrollregion = canvas.bbox('all'))

# This is an example of using my new class I defined above.
# It's how I know my class isn't working quite right.
root = Tk()
autoScrollable = AutoScrollable(root)
autoScrollable.grid(row = 0, column = 0, sticky = 'news')
root.rowconfigure(0, weight = 1)
root.columnconfigure(0, weight = 1)

for i in xrange(10):
    for j in xrange(10):
        button = Button(autoScrollable.frame, text = '%d, %d' % (i, j))
        button.grid(row = i, column = j, sticky = 'news')

autoScrollable.frame.update_idletasks()

root.mainloop()

这是 autoScrollbar 的源代码,我之所以将其包含在内,是因为我将其导入到上述源代码中,但我认为实际的问题并不在这里。

# Adapted from here: http://effbot.org/zone/tkinter-autoscrollbar.htm

from Tkinter import Scrollbar

class AutoScrollbar(Scrollbar):
    '''
    A scrollbar that hides itself if it's not needed. 
    Only works if you use the grid geometry manager.
    '''
    def set(self, lo, hi):
        if float(lo) <= 0.0 and float(hi) >= 1.0:
            self.grid_remove()
        else:
            self.grid()
        Scrollbar.set(self, lo, hi)

    def pack(self, *args, **kwargs):
        raise TclError('Cannot use pack with this widget.')

    def place(self, *args, **kwargs):
        raise TclError('Cannot use pack with this widget.')

最佳答案

您正在调用 canvas.config(scrollregion = canvas.bbox('all'))当 Canvas 仍然为空时,有效地使滚动区域 (0, 0, 1, 1) .

您应该等待定义滚动区域,直到框架中包含小部件。为此,您应该重命名 canvasself.canvas在您的 AutoScrollable 类中并调用

autoScrollable.canvas.config(scrollregion = autoScrollable.canvas.bbox('all'))

紧接着

autoScrollable.frame.update_idletasks()
<小时/>

您还可以绑定(bind) <Configure>事件到您的autoScrollable.frame它调用 update_idletasks()并更新scrollregion 。这样,您就不必再担心自己调用它,因为只要框架的大小发生更改,它们就会更新。

    self.frame.bind('<Configure>', self.frame_changed)

def frame_changed(self, event):
    self.frame.update_idletasks()
    self.canvas.config(scrollregion = self.canvas.bbox('all'))

关于Python Tkinter 可滚动框架类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30018148/

相关文章:

Python tkinter : How can I ensure only ONE child window is created onclick and not a new window every time the button is clicked?

python - 不随 GUI 更新的动态 GUI 的 Tkinter 动态滚动条

python - Python Tkinter 中.xxxxxxx 的含义是什么

wpf - 如果可见,如何在没有垂直滚动条的情况下获取或计算 ListBox 的实际宽度

WPF 列表框向下滚动

python - 如何设置环境变量 R_user 以在 python 中使用 rpy2

python - OpenAI API 错误 : "No module named ' openai. embeddings_utils'; 'openai' 不是包”

python - 从 Python 查询 Windows Server 2008 上的 Oracle 数据库

css - 出现滚动条时元素溢出容器

python - 使用 Django ModelForms 保存数据