Tkinker 滚动条不会一直向下滚动

时间:2021-06-16 15:31:20

标签: python tkinter scrollbar

我创建了一个将 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


enter image description here enter image description here

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

3 个答案:

答案 0 :(得分:0)

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

scroll_bar = Scrollbar(root)

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

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

scroll_bar.config(command = mylist.yview)

答案 1 :(得分:0)

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

您不能在具有相同 pack 的小部件上同时使用 gridmaster。第一个将调整小部件的大小。另一个将看到更改,并调整所有内容以适应其自身的约束。第一个将看到这些更改并再次调整所有内容以适应其约束。另一个将看到更改,以此类推。他们将陷入永远的至高无上的斗争中。

    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')

样本输出:

enter image description here

答案 2 :(得分:0)

部分问题在于您在整个代码中散布了布局代码,这使得布局难以可视化。问题的第二部分是您使用的是 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)
相关问题