【问题标题】:How to insert scrollbar into canvas filled with buttons?如何将滚动条插入到充满按钮的画布中?
【发布时间】:2022-01-05 13:19:51
【问题描述】:

我正在尝试将滚动条插入到充满按钮的画布中(按钮也可以切换为可点击的文本)。

使用下面的代码,窗口看起来没问题。

但是,当我使用滚动条取消注释行时,窗口几何图形会打乱。

谁能帮忙找出代码有什么问题?

系统:Windows 10,python 3.9.6。

import tkinter as tk

class tWindow(tk.Tk):
    frame = None
    canvas = None
    scrollbar = None

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.geometry("640x480+50+50")
        self.setup_frame()
        self.setup_canvas()

    def setup_frame(self):
        self.frame = tk.Frame(master=self, width=640, height=480)
        self.frame.configure(bg="#003163")
        self.frame.place(x=0, y=0)

    def setup_canvas(self):
        self.update()
        self.canvas = tk.Canvas(master=self.frame, bg="#006331",
            width=int(self.frame.winfo_width() / 4), height=self.frame.winfo_height())
        self.canvas.place(x=0, y=0)
        self.update()

        # self.scrollbar = tk.Scrollbar(master=self.canvas, orient=tk.VERTICAL)
        # self.scrollbar.pack(side=tk.RIGHT, fill=tk.BOTH, expand=tk.TRUE)
        # self.canvas.configure(yscrollcommand=self.scrollbar.set)
        # self.scrollbar.configure(command=self.canvas.yview)
        # self.update()

        tmp_pos = 0

        for i in range(20):
            btn_tmp = tk.Button(master=self.canvas, text=f"testing testing testing testing testing {i:02} ...",
                justify=tk.LEFT, wraplength=self.canvas.winfo_width(), bg="#00c0c0", fg="#000000")
            btn_tmp.place(x=0, y=tmp_pos)
            self.update()
            tmp_pos = btn_tmp.winfo_y() + btn_tmp.winfo_height()

def main():
    app = tWindow()
    app.mainloop()

if __name__ == "__main__":
    main()

【问题讨论】:

  • @Thingamabobs:这没有帮助,或者我无法理解。我的意图是仅为“画布”(cyan 区域)插入滚动条。使用链接中的答案,我能够将滚动条插入整个“窗口”(navy 区域)。
  • 你为什么要在画布上设置滚动条?这是一个问题,不是无法解决的,但如果你不做任何事情,你的滚动条会被滚动掉。
  • @Thingamabobs: navy 区域是根据按下的按钮(位于 cyan 区域中)打印一些文本(通过 SQL) )。

标签: python python-3.x tkinter scrollbar


【解决方案1】:

查看代码中的 cmets 作为我提供的 the link 的补充。另请参阅为什么 update is considered harmfullhow do I organize my tkinter gui 了解更多详情。

import tkinter as tk

class tWindow(tk.Tk):
    frame = None
    canvas = None
    scrollbar = None

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.geometry("640x480+50+50")
        self.setup_frame()
        self.setup_canvas()

    def setup_frame(self):
        self.frame = tk.Frame(master=self, width=640, height=480,bg="#003163")
        self.frame.pack(side='left',fill='both',expand=True)##pack left
##        self.frame.place(x=0, y=0) ##place requiers too think to much

    def setup_canvas(self):
##        self.update() ##update is harmfull
        self.canvas = tk.Canvas(master=self.frame, bg='orange',#"#006331",
            width=int(self.frame.winfo_reqwidth() / 4), height=self.frame.winfo_reqheight())
        ##use reqwidth/hight to avoid the use of update. 
        ##It takes the requested size instead the actual
        self.canvas.pack(side='left')

        self.canvas_frame = tk.Frame(self.canvas,bg="#006331")
        ##frame to pack buttons in canvas
        self.canvas.create_window((0,0), window=self.canvas_frame, anchor="nw")
        ##show frame in canvas

        self.scrollbar = tk.Scrollbar(master=self.frame, orient=tk.VERTICAL)
        self.scrollbar.pack(side='left',fill='y')
        
        self.canvas.configure(yscrollcommand=self.scrollbar.set)
        self.scrollbar.configure(command=self.canvas.yview)
        self.canvas_frame.bind('<Configure>',self.oncanvasconfigure)
        ##bind event configure to update the scrollregion

        for i in range(20):
            btn_tmp = tk.Button(master=self.canvas_frame, text=f"testing testing testing testing testing {i:02} ...",
                justify=tk.LEFT, wraplength=self.canvas.winfo_reqwidth(), bg="#00c0c0", fg="#000000")
            btn_tmp.pack()
    def oncanvasconfigure(self,event):
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

def main():
    app = tWindow()
    app.mainloop()

if __name__ == "__main__":
    main()

【讨论】:

  • 首先,非常感谢!我认为我的问题是同时使用place(用于框架和画布)和pack(用于滚动条)方法,对吧?
  • @ssd 你遇到了一些问题。您已将按钮放置在画布上,将小部件添加到画布的正确方法是给我们create_window,因此主要使用框架。另一件事是,正如您所说,与包混合在一起。只有少数情况下 place 确实有意义。我要提到的另一件事是,您从未设置滚动区域,也没有更新它的事件,所以滚动条从来没有用过。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 2021-08-16
  • 2014-07-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多