You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter如何使用单个垂直滚动条同时控制两个Canvas画布滚动

单垂直滚动条同步控制双Canvas实现方案

核心修改逻辑

  • 移除重复的垂直滚动条代码,仅保留1个公共垂直滚动条放在布局最右侧
  • 自定义垂直滚动同步回调,滚动触发时同时更新两个画布的垂直视口
  • 将两个画布的垂直滚动状态变更事件都绑定到公共滚动条,保证滚动条显示位置与画布状态一致
  • 补充跨平台鼠标滚轮事件绑定,画布区域滚动时也能同步两个画布的垂直位置

修改后的完整可运行代码如下:

from tkinter import *
from tkinter import ttk

class MainUI:
    def __init__(self, root):
        mainframe = Frame(root)
        mainframe.grid(column=0, row=0, sticky=(N,W,E,S))
        # 配置行列权重,窗口缩放时画布自适应
        mainframe.grid_rowconfigure(0, weight=1)
        mainframe.grid_columnconfigure(0, weight=1)
        mainframe.grid_columnconfigure(1, weight=1)

        # 第一个画布(红三角)
        self.canvas1 = Canvas(mainframe, background="turquoise")
        self.canvas1.grid(column=0, row=0, sticky=(N,S,W,E))
        # 第一个画布独立水平滚动条
        canvas1_hscroller = Scrollbar(mainframe, orient="horizontal",command=self.canvas1.xview)
        canvas1_hscroller.grid(column=0, row=1, sticky=(W,E))
        self.canvas1.configure(xscrollcommand=canvas1_hscroller.set)

        points = [0,0,1000,800,800,1000]
        triangle = self.canvas1.create_polygon(points,fill="red")
        self.canvas1.configure(scrollregion=self.canvas1.bbox("all"))

        # 第二个画布(绿三角)
        self.canvas2 = Canvas(mainframe, background="orange")
        self.canvas2.grid(column=1, row=0, sticky=(N,S,W,E))
        # 第二个画布独立水平滚动条
        canvas2_hscroller = Scrollbar(mainframe, orient="horizontal",command=self.canvas2.xview)
        canvas2_hscroller.grid(column=1, row=1, sticky=(W,E))
        self.canvas2.configure(xscrollcommand=canvas2_hscroller.set)

        points = [0,0,1000,800,800,1000]
        triangle = self.canvas2.create_polygon(points,fill="green")
        self.canvas2.configure(scrollregion=self.canvas2.bbox("all"))

        # 公共垂直滚动条
        self.vscroller = Scrollbar(mainframe, orient="vertical", command=self.sync_yview)
        self.vscroller.grid(column=2, row=0, sticky=(N,S))
        # 两个画布的垂直滚动状态都同步到公共滚动条
        self.canvas1.configure(yscrollcommand=self.update_vscroller)
        self.canvas2.configure(yscrollcommand=self.update_vscroller)

        # 绑定鼠标滚轮事件,适配Windows和Linux系统
        self.canvas1.bind("<MouseWheel>", self.on_mousewheel)
        self.canvas2.bind("<MouseWheel>", self.on_mousewheel)
        self.canvas1.bind("<Button-4>", self.on_mousewheel)
        self.canvas1.bind("<Button-5>", self.on_mousewheel)
        self.canvas2.bind("<Button-4>", self.on_mousewheel)
        self.canvas2.bind("<Button-5>", self.on_mousewheel)

    # 同步两个画布的垂直滚动
    def sync_yview(self, *args):
        self.canvas1.yview(*args)
        self.canvas2.yview(*args)

    # 同步更新滚动条的显示位置
    def update_vscroller(self, *args):
        self.vscroller.set(*args)

    # 鼠标滚轮滚动回调
    def on_mousewheel(self, event):
        delta = event.delta // 120 if hasattr(event, 'delta') else 1 if event.num == 4 else -1
        self.sync_yview("scroll", -delta, "units")

root = Tk()
ui = MainUI(root)
root.mainloop()

运行后可实现预期效果:两个画布各自保留独立的水平滚动条,仅右侧存在一个垂直滚动条,拖动滚动条或者在任意画布区域滚动鼠标滚轮,都会同步控制两个画布的垂直移动。

内容的提问来源于stack exchange,提问作者Jonathan Allin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 20:36:04