首页 > 编程问答 >即使鼠标位于左侧画布上,右侧画布也会滚动

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

时间:2024-07-29 08:55:17浏览次数:9  
标签:python tkinter tkinter-canvas tkinter-layout

我一直在尝试制作一个程序,根据窗口的宽度有 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"})

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


问题在于使用的是 bind_all <MouseWheel> 事件绑定到 LeftScroll RightScroll 方法。这意味着无论鼠标指针位于何处,都会触发这些绑定,导致右侧画布始终滚动。

要解决此问题,应该使用 bind 而不是 bind_all ,并将事件绑定到特定的画布。这将确保仅当鼠标指针位于相应的画布上方时,才会触发滚动事件。

以下是如何修改代码的方法:

# ... 其他代码 ...

# scroll using the mouse wheel
self.LeftCanvas.bind("<MouseWheel>", self.LeftScroll)

# ... 其他代码 ...

# scroll using the mouse wheel
self.RightCanvas.bind("<MouseWheel>", self.RightScroll)

# ... 其他代码 ...

通过将 bind_all 替换为 bind ,将滚动事件绑定到特定的画布,从而解决了问题并确保只有当鼠标位于目标画布上方时才会滚动。

标签:python,tkinter,tkinter-canvas,tkinter-layout
From: 78803574

相关文章

  • 如何使用python模块捕获用户的文本输入
    我正在开发一个项目,它会检测到如果您按“(”,它会自动关闭它“[”和“{”的情况相同,但重点是它检测键盘按钮“{”或“[”不是字符,这意味着如果朋友有不同的方式输入“[”,它将无法工作,因为该程序用于检测“altgr+(”序列,这可能会影响不同语言的键盘因为您不想在按下......
  • 如何更新 numpy 2 的 python 模块?
    在带有pip的Linux上,新的numpy2似乎可以很好地与pandas配合使用:$python3-c'importnumpyasnp;print(np.__version__);importpandasaspd;print(pd.__version__)'2.0.12.2.2但是,在带有miniconda的Windows上,我得到$${localappdata}/miniconda3/en......
  • python BioChemist 数据集的数据字典/描述
    我正在使用生物化学家数据集。我在哪里可以找到包含每个变量描述的“数据字典”?这就是我正在查看的:importpandasaspdfrompydatasetimportdatadata('bioChemists')我已经用谷歌搜索并尝试寻找运算符,但没有运气!pydataset软件包不包含生物化学家数据集的描述......
  • python中的Telebot API不断断开连接
    使用远程机器人,不断断开服务。我暂时让它在发生这种情况时重新启动。下面是我的代码和错误:importrandomimporttelebotfromtelebot.typesimportInlineKeyboardMarkup,InlineKeyboardButtonfromthreadingimportTimer,Eventfromdotenvimportload_dotenvimporto......
  • 使用 tk.PhotoImage 在 tkinter 窗口中加载 .jpg 图像时出错
    问题:我正在开发一个tkinter应用程序,我需要在GUI中显示图像。虽然加载.png图像工作得很好,但在尝试使用tk.PhotoImage加载.jpg图像时遇到了困难。这是我正在使用的代码片段:`...#Functionfortheadditionalbuttonclickactiondefadditional_f......
  • 如何用Python制作Android服务?
    我想构建一个简单的Android应用程序,例如PushOver应用程序,它具有TCP服务器并接收其记录的文本消息,然后将其作为推送通知发送。这部分已经完成并且工作正常。但即使GUI应用程序关闭,我也想接收消息。我知道这是可能的,因为PushOver应用程序做到了!我想,我可能需要一......
  • Python Discord Bot 的应用程序命令的区域设置名称(多语言别名)
    如何根据用户的语言设置,使应用程序命令的名称具有不同的名称例如,如果一个用户将其discord的语言设置为英语,则用户可以看到英语的应用程序命令名称。另一方面,如果另一个用户将其不和谐语言设置为法语,则用户可以看到法语中的相同应用程序命令的名称。为此,我尝试使用ap......
  • 如何在Python中添加热键?
    我正在为游戏制作一个机器人,我想在按下热键时调用该函数。我已经尝试了一些解决方案,但效果不佳。这是我的代码:defstart():whileTrue:ifkeyboard.is_pressed('alt+s'):break...defmain():whileTrue:ifkeyboard.is_pr......
  • 在Python中解压文件
    我通读了zipfile文档,但不明白如何解压缩文件,只了解如何压缩文件。如何将zip文件的所有内容解压缩到同一目录中?importzipfilewithzipfile.ZipFile('your_zip_file.zip','r')aszip_ref:zip_ref.extractall('target_directory')将......
  • 如何在Python中从RSA公钥中提取N和E?
    我有一个RSA公钥,看起来像-----BEGINPUBLICKEY-----MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAvm0WYXg6mJc5GOWJ+5jkhtbBOe0gyTlujRER++cvKOxbIdg8So3mV1eASEHxqSnp5lGa8R9Pyxz3iaZpBCBBvDB7Fbbe5koVTmt+K06o96ki1/4NbHGyRVL/x5fFiVuTVfmk+GZNakH5dXDq0fwvJyVmUtGYA......