如何在tkinter python中为Frame添加滚动条并用鼠标滚轮滚动它?[复制]

How to add a scrollbar for Frame in tkinter python and scroll it with mousewheel? [duplicate]

提问人:Иван Сакаев 提问时间:10/1/2023 最后编辑:Иван Сакаев 更新时间:10/4/2023 访问量:45

问:

我需要在 tkinter 库中使用鼠标滚轮焦烧为 Frame 创建一个滚动条。

我尝试为 Frame 设置 yview,但 frame 没有 yview 方法。scrollbar = Scrollbar(master, command=frame.yview)

我也尝试为滚动条设置 frame.yscroll命令,但它不起作用

请帮帮我。

python tkinter 滚动条 框架 鼠标滚轮

评论

1赞 acw1668 10/1/2023
框架不可滚动。您可以将框架放在画布内并滚动画布以查看框架的不同部分。

答:

0赞 Module_art 10/1/2023 #1

Tkinter 没有可滚动的框架。

您可以执行的操作:
创建一个 Canvas 并使其可滚动。就像 acw1668 说的。
我为此创建了一个仅在 Linux 上运行的类

import tkinter as tk

class Scroll_Frame(tk.Frame):
    """ frame_options is the scrollable frame"""
    def __init__(self, master=None, bg="grey22", height=300, width=300, *args, **kwargs):
        self.master = master
        self.height_ = height
        self.width_ = width
        self.background = bg
        tk.Frame.__init__(self, self.master)
        self.grid()
        self.rowconfigure((0), weight=1)
        self.columnconfigure((0), weight=1)
        
        self.flag_focus_canvas = False
        
        self.canvas_scroll = tk.Canvas(self, bg=self.background, height=self.height_, width=self.width_, *args, **kwargs)
        self.canvas_scroll.grid(row=0, column=0, sticky="wesn")#, padx=20, pady=20)
        
        self.scrollbar_v = tk.Scrollbar(self, orient="vertical", 
                                         command=self.canvas_scroll.yview)
        self.scrollbar_v.grid(row=0, column=2, sticky="ns")
        self.canvas_scroll.configure(yscrollcommand=self.scrollbar_v.set) 
               
        self.scrollbar_h = tk.Scrollbar(self, orient="horizontal", 
                                         command=self.canvas_scroll.xview)
        self.scrollbar_h.grid(row=1, column=0, sticky="we")
        self.canvas_scroll.configure(xscrollcommand=self.scrollbar_h.set) 
        
        self.frame_options = tk.Frame(self.canvas_scroll, bg=self.background, *args, **kwargs)

        self.frame_options.bind("<Configure>", 
                                lambda e: self.canvas_scroll.configure(scrollregion=self.canvas_scroll.bbox("all")))

        self.canvas_scroll.create_window(0,0, window=self.frame_options, anchor="nw", tags="scrollable")
        
        self.canvas_scroll.bind_all("<Button-4>", lambda e: self._on_mousewheel(e))
        self.canvas_scroll.bind_all("<Button-5>", lambda e: self._on_mousewheel(e))
        self.canvas_scroll.bind("<Enter>", lambda e: self.set_focus_scroll(e))
        self.canvas_scroll.bind("<Leave>", lambda e: self.unset_focus_scroll(e))
    
    def set_focus_scroll(self, event):
        self.flag_focus_canvas = True

    def unset_focus_scroll(self, event):
        self.flag_focus_canvas = False
        
    def _on_mousewheel(self, event):
        if event.num == 4:
            if self.flag_focus_canvas:
                self.canvas_scroll.yview_scroll(int(-1), "units")
        if event.num == 5:
            if self.flag_focus_canvas:
                self.canvas_scroll.yview_scroll(int(1), "units")
                
    def get_scroll_frame(self):
        """returns the real scroll frame,
        this is the place you put all your widgets in"""
        return self.frame_options
        
        
if __name__ == "__main__":
    root = tk.Tk()
    app = Scroll_Frame(root)  
    scroll_frame = app.get_scroll_frame()  
    for i in range(20):
        tk.Button(scroll_frame, text=f"Button {i}").grid(sticky="we")
    root.mainloop()      

现在你可以得到框架 scroll_frame = app.get_scroll_frame() 并放入任何你想要的东西,出于演示目的,我放了按钮。

Windows 会创建不同的事件,因此需要更改绑定:

#Windows bind mousewheel
                
def _on_mousewheel(self, event):
    if self.flag_focus_canvas:
        self.canvas_scroll.yview_scroll(int(-1*(event.delta/120)), "units")
        
self.canvas_scroll.bind("<MouseWheel>", self._on_mousewheel)  

享受

评论

0赞 TheLizzard 10/1/2023
对于 Linux,请检查 .它会告诉您用户是否正在使用触摸板水平滚动。还有你为什么有?我认为没有必要。if event.state&1 != 0self.frame_options.grid(row=0, column=0, sticky="wesn")
0赞 Module_art 10/2/2023
@TheLizzard 你是对的,它是我项目中的一件工件,我会删除它。谢谢
0赞 Иван Сакаев 10/4/2023
您也可以将 self._on_mousewheel() 函数与事件 <MouseWheel> 绑定,并且您需要像这样更改滚动inself._on_mousewheel,它也可以在 Windows 上运行self.canvas_scroll.yview_scroll(-event.delta / SPEED_DIVISON, "units")