MATLAB使用ginputc替代慢启动的ginput时如何获取点击子图序号
根因定位
翻ginputc的源码就能看到两个和坐标轴逻辑相关的硬伤,完全解释你碰到的现象:
- 交互启动时,函数会临时把当前坐标轴固定为调用ginputc瞬间的gca值——也就是你代码里最后创建的第三个子图,全程不会在鼠标按下时动态更新当前坐标轴的引用。
- 函数文档里提到的、可返回坐标轴句柄的
ax输出,实际存的就是交互启动前缓存的那个固定坐标轴句柄,不是实时捕获的点击位置所属坐标轴,这就是你带ax输出的代码依然匹配失败的原因。
修复方案
方案1:最小化修改ginputc源码,修正坐标轴捕获逻辑
不需要大改代码结构,调整ginputc内部的鼠标点击回调逻辑即可:
- 删掉原回调里直接读取figure固定缓存
CurrentAxes的逻辑 - 鼠标按下的瞬间,通过点击点的实际像素位置,遍历所有坐标轴的显示范围,反向定位命中的坐标轴
- 把命中的坐标轴作为
ax输出值返回,同时同步设置为当前gca,对齐原生ginput的交互行为
核心补丁参考代码:
% 替换原鼠标回调内获取当前坐标轴的旧逻辑 click_pos = get(fig_handle, 'CurrentPoint'); fig_size = get(fig_handle, 'Position'); all_ax = findall(fig_handle, 'type', 'axes'); hit_ax = []; for ax_idx = 1:length(all_ax) ax_pos = get(all_ax(ax_idx), 'Position'); % 按归一化坐标转像素判断点击是否落在坐标轴范围内 if click_pos(1) >= ax_pos(1)*fig_size(1) && ... click_pos(1) <= (ax_pos(1)+ax_pos(3))*fig_size(1) && ... click_pos(2) >= ax_pos(2)*fig_size(2) && ... click_pos(2) <= (ax_pos(2)+ax_pos(4))*fig_size(2) hit_ax = all_ax(ax_idx); break end end % 后续把hit_ax赋值给原逻辑中的ax变量即可
注意:判断范围时可以加一层过滤,只保留你预先存在hAx_mine数组里的句柄,避免误匹配图例、色条这类附属坐标轴对象。
方案2:不修改第三方源码,外部捕获点击命中的坐标轴
这个方法改动量最小,也完全不受ginputc内部修改gca状态的影响:
利用MATLAB实时返回当前选中图形对象的gco机制,在调用ginputc前绑定一个临时鼠标点击回调,实时记录点击命中的对象,再通过对象向上追溯所属的坐标轴,核心代码参考:
figure; hAx_mine(1) = subplot(1,3,1); hAx_mine(2) = subplot(1,3,2); hAx_mine(3) = subplot(1,3,3); % 绑定临时点击监听,实时记录点击命中的图形对象 set(gcf, 'WindowButtonDownFcn', @(src,evt) assignin('base','tmp_clicked_obj', gco)); % 调用ginputc完成交互 [x, y, button] = ginputc(1); % 读取记录的点击对象,向上匹配所属坐标轴 clicked_obj = evalin('base', 'tmp_clicked_obj'); if ~isempty(clicked_obj) hit_ax = ancestor(clicked_obj, 'axes'); [~, subplot_idx] = ismember(hit_ax, hAx_mine); disp(['点击对应的子图序号为:', num2str(subplot_idx)]) end
这个方案的可靠性更高,因为gco是系统实时返回的鼠标选中对象,不管ginputc内部如何修改gca的状态,都不会篡改实时的对象选中结果。
内容的提问来源于stack exchange,提问作者Nico
相关产品推荐
相关产品推荐

