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

Matplotlib中Rectangle.contains(event)始终返回True的问题求助

问题解决:正确检测Rectangle的点击事件

你的问题出在用线宽(lw)来模拟矩形区域,而非创建有实际面积的矩形,导致contains()判断逻辑失效。当Rectangle的宽度设为0时,它没有实际填充区域,contains()的默认判断会出现异常,总是返回True。

修改后的代码

import matplotlib.transforms as mtransforms
import matplotlib.pyplot as plt
import matplotlib
import numpy as np

fig, ax = plt.subplots()
plt.plot([1,2,3,4,5,6,7,8,9,10], [1,2,3,4,5,6,7,8,9,10])
spine_width = 20  # 像素单位
color = ["red", "green", "blue"]

for i in range(3):
    # 计算偏移量:每个竖条的间隔为spine_width像素
    shift = spine_width * i + spine_width / 2
    # 将像素偏移转换为轴坐标的偏移(基于DPI)
    offset_dots = shift / 72  # 72DPI是默认,转换为英寸
    # 组合变换:轴坐标 + 像素偏移
    combitransform = (ax.transAxes
                      + mtransforms.ScaledTranslation(offset_dots, 0, 
                                                     fig.canvas.figure.dpi_scale_trans))
    
    # 关键修改:创建有实际宽度的矩形,而非依赖lw
    # 宽度:将spine_width像素转换为轴坐标宽度
    width_inches = spine_width / 72
    # 转换为轴坐标下的宽度(轴坐标x范围是0-1,对应图的宽度)
    ax_width = ax.get_window_extent().width / fig.dpi
    width = width_inches / ax_width
    
    # 创建矩形:位置(1,0),宽度width,高度1,填充颜色(代替lw)
    rectangle = matplotlib.patches.Rectangle((1, 0), width, 1, 
                                             facecolor=color[i], alpha=0.5, 
                                             transform=combitransform, clip_on=False)

    ax.add_patch(rectangle)

    def on_press(event, rectangle, i):
        # 使用contains_point,并指定判断线宽/填充区域
        if rectangle.contains_point((event.x, event.y), radius=0):
            print(f"Clicked on rectangle {i+1} at {event.x} {event.y}!")

    fig.canvas.mpl_connect('button_press_event', 
                           lambda event, rectangle=rectangle, i=i: on_press(event, rectangle, i))

plt.show()

核心修改点

  • 创建有实际面积的矩形:将原来宽度为0、靠lw显示的矩形,改为设置实际宽度(从像素转换为轴坐标),用填充色(facecolor)显示区域,这样contains()能正确识别点击范围。
  • 使用contains_point替代默认contains:contains_point可以更精确地控制判断逻辑,radius=0确保只检测填充区域内的点击。
  • 调整坐标转换:正确将像素单位的宽度转换为轴坐标单位,保证矩形的实际显示大小与预期一致。

线框样式适配方案

如果需要保留线框样式而非填充,也可以设置edgecolor和linewidth,同时给矩形设置极小的填充宽度,再用contains_point的radius参数包含线宽区域:

rectangle = matplotlib.patches.Rectangle((1, 0), 1e-6, 1, 
                                         edgecolor=color[i], linewidth=spine_width,
                                         facecolor='none', alpha=1,
                                         transform=combitransform, clip_on=False)
# 检测时包含线宽区域
if rectangle.contains_point((event.x, event.y), radius=spine_width/2):

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 04:35:26