即使鼠标位于左侧画布上,右侧画布也会滚动

问题描述 投票:0回答:1

我一直在尝试制作一个程序,根据窗口的宽度有 3 种布局(使用 Tkinter)。

问题出在中等布局上。每当我将鼠标放在左侧画布上并使用 MouseWheel 时,右侧画布就会滚动,而左侧画布应该滚动。当我的鼠标放在右侧画布上并使用鼠标滚轮时,右侧画布会滚动。我找不到任何解决方案。

import tkinter as tk
from tkinter import ttk
import random as rand

class App(tk.Tk):
    def init(self, Geometry, Icon, MinimumSizesDictionary):
        super().init() 

        self.title("Practise")
        self.geometry(f"{Geometry[0]}x{Geometry[1]}")
        self.minsize(Geometry[0], Geometry[1])
        self.iconbitmap(Icon)
    
        # variables
    
        self.MinimumSizesDictionary = MinimumSizesDictionary
    
        # widgets
    
        self.LayoutNSizeChecker = LayoutNSizeChecker(self, self.MinimumSizesDictionary)
    
        # run
        self.mainloop()
class LayoutNSizeChecker(ttk.Frame):
    def __init__(self, Parent, MinimumSizesDictionary):
        super ().__init__(Parent)

        self.pack(expand = True, fill = "both")
        self.MinimumSizesDictionary = MinimumSizesDictionary
        self.MinimumSize = self.CurrentMinimumSize = None
        self.Layout = None
    
        # binding an event to the main frame
        self.bind("<Configure>", lambda event : self.Update())
    
        # binding an event to the window
        Parent.bind("<Configure>", lambda event : self.CheckScreenSize(event, Parent))
    
    def CheckScreenSize(self, event, Window):
        if event.widget == Window:
    
            for Key, Value in self.MinimumSizesDictionary.items():
                self.Delta = event.width - Key
    
                if self.Delta >= 0: self.MinimumSize = Key
    
            if self.CurrentMinimumSize != self.MinimumSize:
                self.CurrentMinimumSize = self.MinimumSize
    
                if self.CurrentMinimumSize == 300:
                    for Widget in self.winfo_children():
                        Widget.destroy()
                        self.Destroyed = True
    
                    print("small layout")
                    self.Layout = "Small"
    
                    # variables
    
                    self.NumberOfButtons = 20
                    self.SpaceEachRowTakes = 100
                    self.TotalHeight = self.NumberOfButtons * self.SpaceEachRowTakes
    
                    # canvas
                    self.Canvas = tk.Canvas(self, scrollregion = (0, 0, self.winfo_width(), self.TotalHeight))
                    self.Canvas.pack(expand = True, fill = "both")
    
                    # canvas frame
                    self.CanvasFrame = ttk.Frame(self)
    
                    # scroll bar
                    self.ScrollBar = ttk.Scrollbar(self, orient = "vertical", command = self.Canvas.yview)
                    self.ScrollBar.place(relx = 1, rely = 0, relheight = 1, anchor = "ne")
                    self.Canvas.config(yscrollcommand = self.ScrollBar.set)
    
                    # scroll using the mousewheel
                    self.Canvas.bind_all("<MouseWheel>", lambda event : self.Scroll(event))
    
                    for i in range(1, 21):
                        self.FramePortion = ttk.Frame(self.CanvasFrame)
    
                        # variables
    
                        self.TextData = ["hello!", "goodbye!", "cya", "innit", "lol", "xd", "alr", "bro", "dude", "wsg"]
    
                        # making the grid
    
                        self.FramePortion.rowconfigure(0, weight = 1, uniform = "z")
                        self.FramePortion.columnconfigure((0, 1, 2), weight = 1, uniform = "z")
    
                        # the widgets
                                    
                        self.Button1 = ttk.Button(self.FramePortion, text = i)
                        self.Button2 = ttk.Button(self.FramePortion, text = rand.choice(self.TextData))
                        self.Button3 = ttk.Button(self.FramePortion, text = rand.choice(self.TextData))
    
                        # placing the widgets onto the grid we created earlier
    
                        self.Button1.grid(row = 0, column = 0, sticky = "nesw", padx = 5, pady = 5)
                        self.Button2.grid(row = 0, column = 1, sticky = "nesw", padx = 5, pady = 5)
                        self.Button3.grid(row = 0, column = 2, sticky = "nesw", padx = 5, pady = 5)
                        self.FramePortion.pack(expand = True, fill = "both")
                        self.Destroyed = False
                        
                elif self.CurrentMinimumSize == 600:
                    print("medium layout")
                    self.Layout = "Medium"
    
                    for Widget in self.winfo_children():
                        Widget.destroy()
                        self.Destroyed = True
    
                    # grid for main frame
    
                    self.rowconfigure(0, weight = 1, uniform = "z")
                    self.columnconfigure((0, 2), weight = 6, uniform = "z")
                    self.columnconfigure((1, 3), weight = 1, uniform = "z")
    
                    # left side layout
                    self.LeftFrame = ttk.Frame(self)
                    self.LeftFrame.grid(row = 0, column = 0, sticky = "nesw")
                    self.LeftCanvas = tk.Canvas(self.LeftFrame, scrollregion = (0, 0, self.LeftFrame.winfo_width(), self.TotalHeight / 2))
                    self.LeftCanvas.pack(side = "left", pady = 10, expand = True, fill = "both")
    
                    self.LeftCanvasFrame = ttk.Frame(self.LeftCanvas)
    
                    # scroll bar
                    self.LeftScrollBar = ttk.Scrollbar(self, orient = "vertical", command = self.LeftCanvas.yview)
                    self.LeftScrollBar.grid(row = 0, column = 1, sticky = "ns")
                    self.LeftCanvas.config(yscrollcommand = self.LeftScrollBar.set)
    
                    # scroll using the mouse wheel
                    self.LeftCanvas.bind_all("<MouseWheel>", lambda event : self.LeftScroll(event))

# 

                    for i in range(1, 11):
                        self.LeftFramePortion = ttk.Frame(self.LeftCanvasFrame)
                        self.Button4 = ttk.Button(self.LeftFramePortion, text = i)
                        self.Button5 = ttk.Button(self.LeftFramePortion, text = rand.choice(self.TextData))
                        self.Button6 = ttk.Button(self.LeftFramePortion, text = rand.choice(self.TextData))
                        self.Button4.pack(expand = True, fill = "both", padx = 2.5, pady = 2.5)
                        self.Button5.pack(expand = True, fill = "both", padx = 2.5, pady = 2.5)
                        self.Button6.pack(expand = True, fill = "both", padx = 2.5, pady = 2.5)
                        self.LeftFramePortion.pack(expand = True, fill = "both")
    
                    # right side layout
                    self.RightFrame = ttk.Frame(self)
                    self.RightFrame.grid(row = 0, column = 2, sticky = "nesw")
                    self.RightCanvas = tk.Canvas(self.RightFrame, scrollregion=(0, 0, self.RightFrame.winfo_width(), self.TotalHeight / 2))
                    self.RightCanvas.pack(side = "left", pady = 10, expand = True, fill = "both")
    
                    self.RightCanvasFrame = ttk.Frame(self.RightCanvas)
    
                    # scroll bar
                    self.RightScrollBar = ttk.Scrollbar(self, orient = "vertical", command = self.RightCanvas.yview)
                    self.RightScrollBar.grid(row = 0, column = 3, sticky = "ns")
                    self.RightCanvas.config(yscrollcommand = self.RightScrollBar.set)
    
                    # scroll using the mouse wheel
                    self.RightCanvas.bind_all("<MouseWheel>", lambda event : self.RightScroll(event))
                    for i in range(11, 21):
                        self.RightFramePortion = ttk.Frame(self.RightCanvasFrame)
                        self.Button7 = ttk.Button(self.RightFramePortion, text = i)
                        self.Button8 = ttk.Button(self.RightFramePortion, text = rand.choice(self.TextData))
                        self.Button9 = ttk.Button(self.RightFramePortion, text = rand.choice(self.TextData))
                        self.Button7.pack(expand = True, fill = "both", padx = 2.5, pady = 2.5)
                        self.Button8.pack(expand = True, fill = "both", padx = 2.5, pady = 2.5)
                        self.Button9.pack(expand = True, fill = "both", padx = 2.5, pady = 2.5)
                        self.RightFramePortion.pack(expand = True, fill = "both")
    
                    self.Destroyed = False
    
                elif self.CurrentMinimumSize == 1000:
                    print("large layout")
                    self.Layout = "Large"
    
                    for Widget in self.winfo_children():
                        Widget.destroy()
                        self.Destroyed = True
    
    def Update(self):
        if not self.Destroyed and self.Layout == "Small":
            self.Canvas.create_window(
                (0, 0),
                anchor = "nw",
                window = self.CanvasFrame,
                width = self.winfo_width(),
                height = self.TotalHeight
            )
    
        elif not self.Destroyed and self.Layout == "Medium":
            self.LeftCanvas.create_window(
                (0, 0),
                anchor = "nw",
                window = self.LeftCanvasFrame,
                width = self.LeftFrame.winfo_width(),
                height = self.TotalHeight / 2
            )
    
            self.RightCanvas.create_window(
                (0, 0),
                anchor = "nw",
                window = self.RightCanvasFrame,
                width = self.RightFrame.winfo_width(),
                height = self.TotalHeight / 2
            )
    
    def Scroll(self, event):
        if not self.Destroyed and self.Layout == "Small":
            self.Canvas.yview_scroll(-int(event.delta / 60), "units")
    
    def LeftScroll(self, event): # left scroll bar function for medium layout
        self.LeftCanvas.yview_scroll(-int(event.delta / 60), "units")
    
    def RightScroll(self, event): # right scroll bar function for medium layout
        self.RightCanvas.yview_scroll(-int(event.delta / 60), "units")

App = App([300, 300], "icon.ico", {300 : "Small", 600 : "Medium", 1000 : "Large"})

一如既往地在中等布局中,每当我使用鼠标滚轮时,无论如何它都会滚动右侧画布。

python tkinter tkinter-canvas tkinter-layout
1个回答
0
投票

这是因为您在两个画布上都使用了

bind_all()
作为事件
<MouseWheel>
,所以最后一个绑定将覆盖前一个。

您可以

bind_all()
到公共回调并找到相应的要滚动的画布小部件:

...
self.LeftCanvas.bind_all("<MouseWheel>", self.scroll_canvas) # bind to common callback
...
self.RightCanvas.bind_all("<MouseWheel>", self.scroll_canvas) # bind to common callback
...

以及常见的回调:

def scroll_canvas(self, event):
    # find the canvas widget
    widget = event.widget
    root = widget.winfo_toplevel()
    while widget != root and not isinstance(widget, tk.Canvas):
        widget = widget.master
    # if it is a canvas widget, do the scrolling
    if isinstance(widget, tk.Canvas):
        widget.yview_scroll(-event.delta//60, 'units')
© www.soinside.com 2019 - 2024. All rights reserved.