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

求助:实现Tkinter Canvas内图片随垂直滚动条滑动的示例代码

解决Tkinter Canvas垂直滚动条控制内部图片/图表滚动问题

原代码核心问题

  • 变量self.canvas被重复赋值:先创建了用于滚动的Tkinter Canvas,随后又被Matplotlib的FigureCanvasTkAgg实例覆盖,导致滚动条绑定对象错误。
  • 未设置Canvas的滚动区域,无法识别内部内容的范围。
  • 布局方式混用(place/grid),导致组件位置混乱。

修正后的完整代码

import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import matplotlib
matplotlib.use("TkAgg")

class Main_LEAS(tk.Tk):
    def __init__(self):
        super().__init__()
        self.frame = tk.Frame(self, bg="DodgerBlue4")
        self.frame.pack(fill=tk.BOTH, expand=True)
        self.init_main()
        self.buildbutton()

    def buildbutton(self):
        self.buttonOne = tk.Button(self.frame, text="分析", width=25)
        self.buttonOne.bind('<Button-1>', lambda event: (self.clear(), self.runOne()))
        self.buttonOne.grid(row=1, column=0, pady=10, padx=10)

    def clear(self):
        for widget in self.frame.winfo_children():
            widget.destroy()

    def init_main(self):
        toolbar = tk.Frame(self.frame, bd=2)
        toolbar.pack(side=tk.TOP, fill=tk.X)

    def plot(self):
        # 主容器布局调整
        self.frame.geometry('850x650+50+50')
        
        # 创建带滚动条的Canvas容器
        self.scroll_canvas = tk.Canvas(self.frame, highlightthickness=0, bg="grey", width=500, height=600)
        self.scroll_canvas.place(x=250, y=100)
        
        # 内部放置图表的Frame
        self.plot_container = tk.Frame(self.scroll_canvas, background="#ffffff")
        plot_container_id = self.scroll_canvas.create_window((4, 4), window=self.plot_container, anchor="nw")
        
        # 创建Matplotlib图表
        fig = Figure(figsize=(5, 5), dpi=100)
        y = [i**2 for i in range(101)]
        plot1 = fig.add_subplot(111)
        plot1.plot(y)
        
        # 将Matplotlib画布放入内部Frame
        self.matplotlib_canvas = FigureCanvasTkAgg(fig, self.plot_container)
        self.matplotlib_canvas.draw()
        self.matplotlib_canvas.get_tk_widget().grid(row=0, column=0, sticky="nsew", padx=10, pady=10)
        
        # 可以添加多张图表/图片,示例添加第二个图表
        fig2 = Figure(figsize=(5, 5), dpi=100)
        y2 = [i for i in range(101)]
        plot2 = fig2.add_subplot(111)
        plot2.plot(y2)
        self.matplotlib_canvas2 = FigureCanvasTkAgg(fig2, self.plot_container)
        self.matplotlib_canvas2.draw()
        self.matplotlib_canvas2.get_tk_widget().grid(row=1, column=0, sticky="nsew", padx=10, pady=10)
        
        # 创建垂直滚动条并绑定
        self.vsb = tk.Scrollbar(self.frame, orient="vertical", command=self.scroll_canvas.yview)
        self.vsb.place(x=750, y=100, height=600)
        self.scroll_canvas.configure(yscrollcommand=self.vsb.set)
        
        # 绑定容器大小变化事件,更新滚动区域
        def update_scroll_region(event):
            self.scroll_canvas.configure(scrollregion=self.scroll_canvas.bbox("all"))
        
        self.plot_container.bind("<Configure>", update_scroll_region)

    def runOne(self):
        self.frame.geometry('850x650+50+50')
        self.buildbutton()
        self.plot_button = tk.Button(master=self.frame, command=self.plot, height=2, width=10, text="绘图")
        self.plot_button.place(x=100, y=50)
        return self


if __name__ == "__main__":
    root = Main_LEAS()
    root.title("LEAS500")
    root.geometry('460x150+500+100')
    root.resizable(False, False)
    root.config(bg="DodgerBlue4")
    root.mainloop()

关键修改说明

  1. 分离Canvas角色:将用于滚动的Tkinter Canvas(scroll_canvas)和Matplotlib的画布(matplotlib_canvas)分开,避免变量覆盖。
  2. 设置滚动区域:通过绑定内部Frame的<Configure>事件,动态更新Canvas的scrollregion,确保滚动条能识别全部内容范围。
  3. 正确绑定滚动条:滚动条的command绑定到scroll_canvas.yview,Canvas的yscrollcommand绑定到滚动条的set方法,实现双向联动。
  4. 统一布局逻辑:调整组件位置,确保滚动条和Canvas的尺寸、位置匹配,内部图表垂直排列以触发滚动效果。

内容的提问来源于stack exchange,提问作者MIKKI MOUSE

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 23:37:03