如何正确将左侧画布和右侧画布的滚动条绑定到滚轮事件?

huangapple go评论84阅读模式
英文:

How to bind scrollbar of left canvas and right canvas to wheel events correctly?

问题

I have two scrollbars, i.e. on the left and right frame. I have created two mouse events to bind scroll wheel with each scrollbar. If I am on the left frame and I scroll with the scroll wheel, I would expect that the left frame's scrollbar would scroll, too. But, in my implementation, only the right frame's scrollbar moves. I could not figure out the problem in my script. I appreciate any help.

英文:

I have two scrollbars, i.e. on the left and right frame. I have created two mouse events to bind scroll wheel with each scrollbar. If I am on left frame and I scroll with scroll wheel, I would expect that scrollbar of left frame would scroll, too. But, in my implementation, only scrollbar of right frame moves. I could not figure out the problem in my script. I appreciate any help.

import tkinter as tk
from tkinter import ttk
import pandas as pd
import random

# Sample DataFrame
df = pd.DataFrame({
    'ID': [1, 2, 3, 4, 5],
    'Data': [10, 15, 7, 12, 9]
})

def create_radial_chart(frame):
    # Function to create a random radial chart
    # Replace this with your own radial chart creation code
    # For demonstration purposes, we'll just create a random number of labels
    num_labels = random.randint(1, 80)
    labels = [f'Label {i}' for i in range(1, num_labels + 1)]
    radial_chart = ttk.Label(frame, text='\n'.join(labels))
    radial_chart.pack()

def on_left_canvas_scroll(event):
    left_canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
    update_left_scrollbar()

def update_left_scrollbar():
    left_scrollbar.set(*left_canvas.yview())

# Create the main window
root = tk.Tk()
root.title('Tkinter Layout Example')

# Create the dropdown menu
dropdown_var = tk.StringVar(root)
dropdown = ttk.Combobox(root, textvariable=dropdown_var)
dropdown['values'] = df['ID'].unique()
dropdown.pack()

# Create the main frames
main_frame = ttk.Frame(root)
main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

# Create the left frame with a scrollbar
left_frame = ttk.Frame(main_frame)
left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

left_scrollbar = ttk.Scrollbar(left_frame, orient=tk.VERTICAL)
left_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

left_canvas = tk.Canvas(left_frame, yscrollcommand=left_scrollbar.set)
left_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

left_scrollbar.config(command=left_canvas.yview)

# Bind scroll wheel event to the left frame content
left_frame_content = ttk.Frame(left_canvas)
left_canvas.create_window((0, 0), window=left_frame_content, anchor='nw')
left_frame_content.bind_all("<MouseWheel>", on_left_canvas_scroll)

# Create the radial charts in the left frame
for _ in range(5):
    create_radial_chart(left_frame_content)

# Configure the scrollable region for the left canvas
left_frame_content.update_idletasks()
left_canvas.config(scrollregion=left_canvas.bbox("all"))

# Update the left scrollbar initially
update_left_scrollbar()

# Create the right frame with a scrollbar
right_frame = ttk.Frame(main_frame)
right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

right_scrollbar = ttk.Scrollbar(right_frame, orient=tk.VERTICAL)
right_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

right_canvas = tk.Canvas(right_frame, yscrollcommand=right_scrollbar.set)
right_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

right_scrollbar.config(command=right_canvas.yview)

# Bind scroll wheel event to the right canvas
right_canvas.bind_all("<MouseWheel>", lambda event: right_canvas.yview_scroll(int(-1 * (event.delta / 120)), "units"))

# Create the middle frames
middle_frame = ttk.Frame(main_frame)
middle_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=10)

upper_middle_frame = ttk.Frame(middle_frame)
upper_middle_frame.pack(fill=tk.BOTH, expand=True)

lower_middle_frame = ttk.Frame(middle_frame)
lower_middle_frame.pack(fill=tk.BOTH, expand=True)

# Create the line plot in the upper middle frame
# Replace this with your own line plot creation code
line_plot = ttk.Label(upper_middle_frame, text='Line Plot')
line_plot.pack()

# Create the data table in the lower middle frame
# Replace this with your own data table creation code
data_table = ttk.Label(lower_middle_frame, text='Data Table')
data_table.pack()

# Create the radial charts in the right frame
right_frame_content = ttk.Frame(right_canvas)
right_canvas.create_window((0, 0), window=right_frame_content, anchor='nw')

for _ in range(5):
    create_radial_chart(right_frame_content)

# Configure the scrollable region for the right canvas
right_frame_content.update_idletasks()
right_canvas.config(scrollregion=right_canvas.bbox("all"))

root.mainloop()

答案1

得分: 1

这是因为 right_canvas.bind_all(...) 会覆盖 left_canvas.bind_all(...)。你需要检查哪个部件触发了事件,然后确定滚动相应的画布:

def mouse_scroll(event):
    # 检查是左侧画布还是左侧画布内的标签触发了事件?
    left = (event.widget is left_canvas) or \
           (event.widget.master and event.widget.master is left_frame_content)
    # 检查是右侧画布还是右侧画布内的标签触发了事件?
    right = (event.widget is right_canvas) or \
            (event.widget.master and event.widget.master is right_frame_content)
    if left:
        left_canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
    elif right:
        right_canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")

# 只需调用一次 `bind_all()`
root.bind_all("<MouseWheel>", mouse_scroll)
英文:

It is because right_canvas.bind_all(...) will override left_canvas.bind_all(...). You need to check which widget triggers the event and determine to scroll the corresponding canvas:

def mouse_scroll(event):
    # Does left canvas or labels inside left canvas trigger the event?
    left = (event.widget is left_canvas) or \
           (event.widget.master and event.widget.master is left_frame_content)
    # Does right canvas or labels inside right canvas trigger the event?
    right = (event.widget is right_canvas) or \
            (event.widget.master and event.widget.master is right_frame_content)
    if left:
        left_canvas.yview_scroll(int(-1 * (event.delta / 120)), &quot;units&quot;)
    elif right:
        right_canvas.yview_scroll(int(-1 * (event.delta / 120)), &quot;units&quot;)

# just call `bind_all()` once 
root.bind_all(&quot;&lt;MouseWheel&gt;&quot;, mouse_scroll)

huangapple
  • 本文由 发表于 2023年5月25日 23:20:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76333910.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定