无法使用鼠标滚轮和鼠标滚动框架添加水平滚动条

无法使用鼠标滚轮和鼠标滚动框架添加水平滚动条

问题描述:

我无法使用鼠标滚轮滚动我的框架.谁能告诉我如何使用鼠标滚轮垂直滚动框架&还告诉我如何将水平滚动条添加到同一帧并使用 Shift+鼠标滚轮滚动它.

I'm Unable to Scroll My Frame using Mouse Wheel. Can anyone tell me how can i Scroll Frame using mouse Wheel Vertically & also tell me how to add a horizontal Scrollbar to same Frame and Scroll it using Shift+Mousewheel.

from tkinter import *
from tkinter.tix import *

root = Tk()
root.wm_title('DEMO SCROLL')
frame = Frame(width="500",height="500")
frame.pack()
swin = ScrolledWindow(frame, width=500, height=500)
swin.pack()
win = swin.window
for i in range(50):
    Label(win,text="hello").pack()
root.mainloop()

你不能滚动 所以我们使用了一个虚拟画布.我们将框架放在画布内,这样当我们滚动画布时,看起来就像是在滚动框架.我们还必须绑定到用户滚动和正在更改的滚动条.

You can't scroll <tkinter.Frame> so we use a dummy canvas. We put the frame inside the canvas so that when we scroll the canvas it looks like we are scrolling the frame. We also have to bind to the user scrolling and the scrollbar being changed.

如果你想把它作为一个类:

If you want it as a class:

import tkinter as tk


FIT_WIDTH = "fit_width"
FIT_HEIGHT = "fit_height"


class ScrollableFrame(tk.Frame):
    """
    There is no way to scroll <tkinter.Frame> so we are
    going to create a canvas and place the frame there.
    Scrolling the canvas will give the illution of scrolling
    the frame
    Partly taken from:
        https://blog.tecladocode.com/tkinter-scrollable-frames/
        https://*.com/a/17457843/11106801

    master_frame---------------------------------------------------------
    | dummy_canvas-----------------------------------------  y_scroll--  |
    | | self---------------------------------------------  | |         | |
    | | |                                                | | |         | |
    | | |                                                | | |         | |
    | | |                                                | | |         | |
    | |  ------------------------------------------------  | |         | |
    |  ----------------------------------------------------  |         | |
    |                                                        |         | |
    | x_scroll---------------------------------------------  |         | |
    | |                                                    | |         | |
    |  ----------------------------------------------------   ---------  |
     --------------------------------------------------------------------
    """
    def __init__(self, master=None, scroll_speed=2,
                 hscroll=False, vscroll=True, **kwargs):
        assert isinstance(scroll_speed, int), "`scroll_speed` must be an int"
        self.scroll_speed = scroll_speed

        self.master_frame = tk.Frame(master)
        self.dummy_canvas = tk.Canvas(self.master_frame, **kwargs)
        super().__init__(self.dummy_canvas)

        # Create the 2 scrollbars
        if vscroll:
            self.v_scrollbar = tk.Scrollbar(self.master_frame,
                                            orient="vertical",
                                            command=self.dummy_canvas.yview)
            self.v_scrollbar.pack(side="right", fill="y")
            self.dummy_canvas.configure(yscrollcommand=self.v_scrollbar.set)
        if hscroll:
            self.h_scrollbar = tk.Scrollbar(self.master_frame,
                                            orient="horizontal",
                                            command=self.dummy_canvas.xview)
            self.h_scrollbar.pack(side="bottom", fill="x")
            self.dummy_canvas.configure(xscrollcommand=self.h_scrollbar.set)

        # Bind to the mousewheel scrolling
        self.dummy_canvas.bind_all("<MouseWheel>", self.scrolling_windows,
                                   add=True)
        self.dummy_canvas.bind_all("<Button-4>", self.scrolling_linux, add=True)
        self.dummy_canvas.bind_all("<Button-5>", self.scrolling_linux, add=True)
        self.bind("<Configure>", self.scrollbar_scrolling, add=True)

        # Place `self` inside `dummy_canvas`
        self.dummy_canvas.create_window((0, 0), window=self, anchor="nw")
        # Place `dummy_canvas` inside `master_frame`
        self.dummy_canvas.pack(side="top", expand=True, fill="both")

        self.pack = self.master_frame.pack
        self.grid = self.master_frame.grid
        self.place = self.master_frame.place
        self.pack_forget = self.master_frame.pack_forget
        self.grid_forget = self.master_frame.grid_forget
        self.place_forget = self.master_frame.place_forget

    def scrolling_windows(self, event):
        assert event.delta != 0, "On Windows, `event.delta` should never be 0"
        y_steps = int(-event.delta/abs(event.delta)*self.scroll_speed)
        self.dummy_canvas.yview_scroll(y_steps, "units")

    def scrolling_linux(self, event):
        y_steps = self.scroll_speed
        if event.num == 4:
            y_steps *= -1
        self.dummy_canvas.yview_scroll(y_steps, "units")

    def scrollbar_scrolling(self, event):
        region = list(self.dummy_canvas.bbox("all"))
        region[2] = max(self.dummy_canvas.winfo_width(), region[2])
        region[3] = max(self.dummy_canvas.winfo_height(), region[3])
        self.dummy_canvas.configure(scrollregion=region)

    def resize(self, fit=None, height=None, width=None):
        if fit == FIT_WIDTH:
            super().update()
            self.dummy_canvas.config(width=super().winfo_width())
        if fit == FIT_HEIGHT:
            super().update()
            self.dummy_canvas.config(height=super().winfo_height())
        if height is not None:
            self.dummy_canvas.config(height=height)
        if width is not None:
            self.dummy_canvas.config(width=width)
    fit = resize


if __name__ == "__main__":
    # Example 1
    root = tk.Tk()
    frame = ScrollableFrame(root, width=300, height=200,
                            hscroll=True, vscroll=True)
    frame.pack()

    for i in range(51):
        label = tk.Label(frame, text=i, anchor="w")
        label.grid(row=i, column=i)

    root.mainloop()

    # Example 2
    root = tk.Tk()
    frame = ScrollableFrame(root, width=300, height=200,
                            hscroll=False, vscroll=True)
    frame.pack()

    for i in range(51):
        label = tk.Label(frame, text=f"Label number {i}")
        label.pack(anchor="w")
    frame.resize(FIT_WIDTH)

    root.mainloop()