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

Matplotlib画布绑定Tkinter框架后点击事件无法触发,求原因

Why isn't your Matplotlib onclick event firing in Tkinter?

Let's break down why your onclick function isn't triggering, and fix it step by step:

The Core Issues

  1. Your Matplotlib canvas isn't actually being displayed in frame1
    You created the FigureCanvasTkAgg object, but never added its underlying Tkinter widget to your parent1 frame. Right now, you're clicking empty space in frame1, not the Matplotlib plot—so no event fires.

  2. Local variable garbage collection
    Your fig and canvas variables are local to the plot() method. Once that method finishes running, Python might clean them up, which breaks the event connection entirely.

Fixed Code

Here's the adjusted version with comments pointing out key changes:

import Tkinter as tk
import ttk
from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg,
    NavigationToolbar2TkAgg)
import matplotlib.pyplot as plt
import numpy as np

class Frame_examples_program():
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("Amazing GUI 5000")
        # Configure main window grid to let frames expand properly
        self.window.grid_rowconfigure(0, weight=1)
        self.window.grid_rowconfigure(1, weight=0)
        self.window.grid_columnconfigure(0, weight=1)
        self.create_widgets()

    def create_widgets(self):
        self.window['padx'] = 10
        self.window['pady'] = 10
        frame1 = ttk.Frame(self.window, relief=tk.RIDGE)
        frame1.grid(row=0, column=0, sticky=tk.E + tk.W + tk.N + tk.S, padx=0, pady=0)
        # Configure frame1 grid to let the canvas fill available space
        frame1.grid_rowconfigure(0, weight=1)
        frame1.grid_columnconfigure(0, weight=1)
        
        frame2 = ttk.Frame(self.window, relief=tk.RIDGE)
        frame2.grid(row=1, column=0, sticky=tk.E + tk.W + tk.N + tk.S, padx=0, pady=0)
        self.plot_frame = PlotFrame(frame1, frame2)

class PlotFrame():
    def __init__(self, parent1, parent2):
        self.parent1 = parent1
        self.parent2 = parent2
        # Store canvas as instance attribute to avoid garbage collection
        self.canvas = self.plot()
        self.plot_toolbar(self.canvas)

    def plot(self):
        # Store fig/ax as instance attributes to keep them in memory
        self.fig, self.ax = plt.subplots()
        self.ax.imshow(np.ones((100,100)), picker=True)
        canvas = FigureCanvasTkAgg(self.fig, self.parent1)
        # Add the canvas widget to parent1 frame so it's visible
        canvas.get_tk_widget().grid(row=0, column=0, sticky=tk.NSEW)
        # Connect the click event to our handler
        canvas.mpl_connect('button_press_event', self.onclick)
        return canvas

    def plot_toolbar(self, canvas):
        toolbar = NavigationToolbar2TkAgg(canvas, self.parent2)
        toolbar.update()
        canvas.draw()

    def onclick(self, event):
        # Optional: print click coordinates for debugging
        print(f'Clicked at x={event.xdata}, y={event.ydata}')
        print('WOHOOOO')

program = Frame_examples_program()
program.window.mainloop()

Key Fixes Explained

  • Grid configuration: We added weight values to the main window and frame1 grids, so the plot canvas expands to fill the available space instead of staying tiny.
  • Instance attributes for plot objects: By storing self.fig, self.ax, and self.canvas, we ensure Python doesn't garbage-collect these objects after the plot() method finishes running.
  • Proper canvas placement: The line canvas.get_tk_widget().grid(...) ensures the plot is actually rendered inside frame1, so clicks register with Matplotlib instead of hitting empty space.
  • Cleaned up toolbar code: Removed the misplaced canvas repositioning call in plot_toolbar that was causing confusion.

Now when you click the plot, your onclick function will fire immediately and print "WOHOOOO" (plus click coordinates if you keep that debug line)!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:25:35