【问题标题】:Tkinker Scrollbar doesn't scroll all the way downTkinter 滚动条不会一直向下滚动
【发布时间】:2021-09-01 10:57:05
【问题描述】:

我创建了一个将 json 文件表示为按钮的 GUI。 我想让 json 结构可滚动。 我能够让它滚动,但只能滚动到文件的中间

import tkinter as tk
import json

class JSONGUI():
    json_example = '{"event":{"name":"test","time":"today"}}'
    s = '{"success": "true", "status": 200, "message": "Hello"}'
    json_example2 = """{
    "glossary": {
        "title": "example glossary",
        "GlossDiv": {
            "title": "S",
            "GlossList": {
                "GlossEntry": {
                    "ID": "SGML",
                    "SortAs": "SGML",
                    "GlossTerm": "Standard Generalized Markup Language",
                    "Acronym": "SGML",
                    "Abbrev": "ISO 8879:1986",
                    "GlossDef": {
                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
                        "GlossSeeAlso": ["GML", "XML"]
                    },
                    "GlossSee": "markup"
                }
            }
        }
    }
}"""

    def __init__(self):
        json_dict = json.loads(self.json_example2)
        #window
        self.window = tk.Tk()
        self.window.title('JSON GUI')
        # self.window.state('zoomed')
        self.window.geometry('500x100')

        #frame
        self.frame = tk.Frame(self.window)
        self.frame.grid(column=0, row=0, sticky='W')
        self.frame.grid_propagate(False)

        #canvas
        self.canvas = tk.Canvas(self.frame)
        self.canvas.grid(column=0, row=0, sticky='news')

        #scrollbar
        myscrollbar = tk.Scrollbar(self.window, orient="vertical", command=self.canvas.yview)
        myscrollbar.grid(column=1, row=0, sticky='ns')
        self.canvas.configure(yscrollcommand=myscrollbar.set)

        #json_frame
        self.frame_json = tk.Frame(self.canvas)
        self.canvas.create_window((0, 0), window=self.frame_json, anchor='nw')

        #logic add buttons
        self.loop_dict(json_dict, 0, 0)

        #others
        self.frame.config(width=450, height=50)
        self.frame_json.update_idletasks()
        self.canvas.config(scrollregion=self.canvas.bbox("all"))

        #mainloop
        self.window.mainloop()

    def test_function(self):
        print('button pressed')

    def loop_dict(self, json_dict, l, c):
        for x in json_dict:
            tk.Button(self.frame_json, text=x, command=self.test_function).grid(row=l, column=c, sticky='W')
            l += 1
            if isinstance(json_dict.get(x), dict):
                c += 1
                l = self.loop_dict(json_dict.get(x), l, c)
            if isinstance(json_dict.get(x), list):
                c += 1
                l = self.loop_list(json_dict.get(x), l, c)
        return l

    def loop_list(self, json_list, l, c):
        tk.Label(self.frame_json, text='list').grid(row=l, column=c, sticky='W')
        l += 1
        for x in json_list:
            if isinstance(x, dict):
                c += 1
                l = self.loop_dict(self, x, l, c)
        return l


所以我可以滚动,但不能进一步滚动,然后显示在第二张图片中。 我注意到如果我改变了宽度和高度,我可以再滚动一点。 这是什么原因造成的?我怎样才能一直向下滚动?

【问题讨论】:

  • 尝试用this替换你的可滚动框架
  • 您是在询问能否滚动,还是询问可滚动区域和/或滚动条未填满窗口?

标签: python tkinter scrollbar


【解决方案1】:

我尝试在我的计算机上运行您的代码,但没有成功。我对您遇到的问题的猜测可能是由于您对滚动条本身的配置。试试这样的东西!它适用于我几个月前做的一个早期项目。

scroll_bar = Scrollbar(root)

scroll_bar.pack( side = RIGHT,
            fill = Y )

mylist = Listbox(root, 
             yscrollcommand = scroll_bar.set)

scroll_bar.config(command = mylist.yview)

【讨论】:

    【解决方案2】:

    您应该使用.pack() 经理。此外,您需要将所有小部件替换为 .grid().pack(),因为它们彼此不协调。

    您不能在具有相同master 的小部件上同时使用packgrid。第一个将调整小部件的大小。另一个将看到更改,并调整所有内容以适应它自己的约束。第一个将看到这些更改并再次调整所有内容以适应其约束。另一个会看到这些变化,以此类推。他们将陷入争夺霸权的永恒斗争中。

        def __init__(self):
            self.window = tk.Tk()
            self.window.title('JSON GUI')
            # self.window.state('zoomed')
            self.window.geometry('500x100')
    
            #frame
            self.frame = tk.Frame(self.window)
            self.frame.pack(fill=tk.Y,side=tk.LEFT)
     
    
            #canvas
            self.canvas = tk.Canvas(self.frame)
            self.canvas.pack(fill=tk.BOTH,expand=1)
    
            #scrollbar
            myscrollbar = tk.Scrollbar(self.window, orient="vertical", command=self.canvas.yview)
            myscrollbar.pack(fill="y",side=tk.RIGHT)
            self.canvas.configure(yscrollcommand=myscrollbar.set)
    
            #json_frame
            self.frame_json = tk.Frame(self.canvas)
            self.canvas.create_window((0, 0), window=self.frame_json, anchor='nw')
    

    样本输出:

    【讨论】:

    • 我认为保留self.frame.grid_propagate(False) 没有意义
    • @TheLizzard,谢谢!我编辑了答案
    【解决方案3】:

    问题的一部分是布局代码散布在整个代码中,这使得布局可视化变得困难。您的问题的第二部分是您正在使用grid,但您从未告诉网格如何处理未分配的空间(即:当窗口大于内部小部件时剩余的空间)。

    必须配置行和列的权重是使用grid 的缺点之一。当您只有在一行或一列中排列的小部件时,pack 通常是更好的选择,因为它需要的代码行数更少。

    在您的情况下,根窗口只有两个小部件:画布和滚动条。由于您只有两个水平排列的小部件,因此我建议您删除grid 的使用,而使用pack,如下所示:

    myscrollbar.pack(side="right", fill="y")
    self.frame.pack(side="left", fill="both", expand=True)
    

    如果您更喜欢使用grid,则必须注意为第 0 列设置权重,以便为其分配所有未分配的空间。您也应该对行执行此操作。如您所见,在这种情况下使用 grid 需要两倍的代码行数,但除此之外它也同样有效。

    self.frame.grid(row=0, column=0, sticky="nsew")
    myscrollbar.grid(row=0, column=1, sticky="ns")
    
    self.window.grid_rowconfigure(0, weight=1)
    self.window.grid_columnconfigure(0, weight=1)
    

    仅此一项就解决了滚动问题。然而,它暴露了另一个问题,即画布没有填满它的窗口。这也是由于没有为任何列或行分配权重,也可以使用pack 更轻松地解决,因为它是其父级中唯一的小部件。

    self.canvas.pack(fill="both", expand=True)
    

    同样,您可以使用grid 代替pack,但您必须注意设置行和列的权重。

    self.canvas.grid(column=0, row=0, sticky='news')
    self.frame.grid_rowconfigure(0, weight=1)
    self.frame.grid_columnconfigure(0, weight=1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-03
      • 2016-07-07
      • 2023-03-11
      • 1970-01-01
      相关资源
      最近更新 更多