findobj

CREATE DEFINER = 'lijiwei'@'192.168.16.33'
PROCEDURE ayst_share.findobj(IN v_object_name VARCHAR(255))
BEGIN

/*
  FUNCTION: 
  该程序的设计目标是,当技术人员输入一个数据库对象(表名、字段名、约束名、索引名、存储过程名等等)时,
  可以智能化显示出用户所输入的对象的相关信息(假如该对象在数据库中存在的话)。以便技术人员快速地获取相关对象
  的定义,方便解决相关问题。

   created date: 2016/9/29 


  */


if (select 1 from information_schema.SCHEMATA where schema_name=v_object_name )
then 
select * from information_schema.SCHEMATA where schema_name=v_object_name    ;
end if ;

if (select 1 from information_schema.ROUTINES where routine_name=v_object_name limit 1) then
select * from information_schema.ROUTINES where routine_name=v_object_name ;
end if ;

if (select 1 from information_schema.tables where table_name=v_object_name limit 1) then
select * from information_schema.tables where table_name=v_object_name ;
end if ;

if (select 1 from information_schema.columns where column_name=v_object_name limit 1 )then
select * from information_schema.columns where column_name=v_object_name ;
  end if ;

if (select 1 from information_schema.table_constraints where constraint_name=v_object_name limit 1) then
select * from information_schema.table_constraints where constraint_name=v_object_name ;
end if ;

if (select 1 from information_schema.TRIGGERS where trigger_name=v_object_name limit 1)then
select * from information_schema.TRIGGERS where trigger_name=v_object_name ;
end if ;

if (select 1 from information_schema.VIEWS where table_name=v_object_name  limit 1)then
select * from information_schema.VIEWS where table_name=v_object_name ;
  end if ;


if (select 1 from information_schema.KEY_COLUMN_USAGE where constraint_name=v_object_name or column_name=v_object_name limit 1 ) then
  select *   from information_schema.KEY_COLUMN_USAGE where constraint_name=v_object_name or column_name=v_object_name ;
end if ;


END
classdef InteractiveDataPlotter < handle properties % 数据存储 dataMap fig axes % UI 组件句柄 keyListbox btnPlotRefresh btnMultiPlot btnSaveCSV % 多图管理 multiPlotFigures = gobjects(0) % 初始化为空图形对象数组 % 选择模式 selectionMode = 'single' % 默认单选模式 % ===== 新增属性 ===== % 缩放控制 zoomMode = 0; % 0=自由, 1=水平, 2=垂直 zoomButtons % 缩放按钮句柄 % 参考线管理 refLines = matlab.graphics.primitive.Line.empty % 参考线对象数组 % 多点标记 dataPoints = struct('x', {}, 'y', {}, 'handle', {}, 'index', {}, 'dataKey', {}) % 修正字段 snapRadius = 0.01 % 吸附半径(相对坐标) % 鼠标交互状态 currentDraggingLine % 当前拖拽的参考线 pointSelectionMode = false % 点标记模式标志 end methods function obj = InteractiveDataPlotter(dataMap) % === 数据验证 === if ~isa(dataMap, 'containers.Map') error('输入必须是 containers.Map 对象'); end if isempty(dataMap) error('输入Map不能为空'); end % 检查所有值是否为数值向量 allKeys = keys(dataMap); for i = 1:length(allKeys) value = dataMap(allKeys{i}); if ~isnumeric(value) || ~isvector(value) error('键 "%s" 的值必须是数值向量', allKeys{i}); end end obj.dataMap = dataMap; obj.createMainUI(); obj.updateAddButtonState(); % 修复4: 初始化按钮状态 end % 创建UI主界面 function createMainUI(obj) obj.fig = uifigure('Name', '交互式数据绘图器', ... 'Position', [100, 100, 1200, 700], ... 'AutoResizeChildren', 'off'); % === 网格布局重构 === mainGrid = uigridlayout(obj.fig, [3, 3]); % 改为3行 mainGrid.RowHeight = {'1x', 100, 60}; mainGrid.ColumnWidth = {220, '1x', 220}; mainGrid.RowSpacing = 10; mainGrid.ColumnSpacing = 15; % === 左侧面板: 数据集选择 === dataPanel = uipanel(mainGrid, 'Title', '数据集选择'); dataPanel.Layout.Row = 1; dataPanel.Layout.Column = 1; dataGrid = uigridlayout(dataPanel, [4, 1]); dataGrid.RowHeight = {25, '1x', 35, 35}; dataGrid.RowSpacing = 8; uilabel(dataGrid, 'Text', '选择数据集:', ... 'FontWeight', 'bold', ... 'HorizontalAlignment', 'left'); % ===== 修复2: 初始化模式同步 ===== if strcmp(obj.selectionMode, 'single') multiSelect = 'off'; else multiSelect = 'on'; end obj.keyListbox = uilistbox(dataGrid, ... 'Items', keys(obj.dataMap), ... 'Multiselect', multiSelect, ... % 与selectionMode同步 'ValueChangedFcn', @(src,evt)obj.plotSelectedData()); modeGrid = uigridlayout(dataGrid, [1, 2]); modeGrid.Padding = [0, 0, 0, 0]; modeGrid.ColumnWidth = {'1x', '1x'}; uibutton(modeGrid, 'Text', '单选模式', ... 'ButtonPushedFcn', @(src,evt)obj.setSelectionMode('single')); uibutton(modeGrid, 'Text', '多选模式', ... 'ButtonPushedFcn', @(src,evt)obj.setSelectionMode('multi')); % === 中央面板: 主绘图区 === plotPanel = uipanel(mainGrid, 'Title', '数据可视化'); plotPanel.Layout.Row = 1; plotPanel.Layout.Column = 2; plotGrid = uigridlayout(plotPanel, [1,1]); obj.axes = uiaxes(plotGrid); title(obj.axes, '数据可视化'); grid(obj.axes, 'on'); hold(obj.axes, 'on'); % === 右侧面板: 多图控制区 === multiPanel = uipanel(mainGrid, 'Title', '多图管理'); multiPanel.Layout.Row = 1; multiPanel.Layout.Column = 3; multiGrid = uigridlayout(multiPanel, [5, 1]); multiGrid.RowHeight = {25, 40, 40, 40, '1x'}; multiGrid.RowSpacing = 10; uilabel(multiGrid, 'Text', '操作:', ... 'FontWeight', 'bold', ... 'HorizontalAlignment', 'left'); % === 缩放控制工具栏 === zoomPanel = uipanel(mainGrid, 'Title', '缩放控制'); zoomPanel.Layout.Row = 2; % 新位置 zoomPanel.Layout.Column = [1, 3]; % 跨列 zoomGrid = uigridlayout(zoomPanel, [1, 5]); zoomGrid.ColumnWidth = repmat({'1x'}, 1, 5); zoomGrid.Padding = [5, 10, 5, 10]; obj.zoomButtons = gobjects(3,1); obj.zoomButtons(1) = uibutton(zoomGrid, ... 'Text', '自由缩放', ... 'ButtonPushedFcn', @(src,evt)obj.setZoomMode(0)); obj.zoomButtons(2) = uibutton(zoomGrid, ... 'Text', '水平缩放', ... 'ButtonPushedFcn', @(src,evt)obj.setZoomMode(1)); obj.zoomButtons(3) = uibutton(zoomGrid, ... 'Text', '垂直缩放', ... 'ButtonPushedFcn', @(src,evt)obj.setZoomMode(2)); uibutton(zoomGrid, ... 'Text', '重置缩放', ... 'ButtonPushedFcn', @(src,evt)resetview(obj.axes)); % 修复函数名 uibutton(zoomGrid, ... 'Text', '重置视图', ... 'ButtonPushedFcn', @(src,evt)view(obj.axes, 0, 90)); % === 参考线工具栏 === toolPanel = uipanel(mainGrid, 'Title', '数据工具'); toolPanel.Layout.Row = 2; % 新位置 toolPanel.Layout.Column = 1; toolGrid = uigridlayout(toolPanel, [1, 6]); toolGrid.ColumnWidth = repmat({'1x'}, 1, 6); toolGrid.Padding = [5, 10, 5, 10]; uibutton(toolGrid, ... 'Text', '添加水平线', ... 'ButtonPushedFcn', @(src,evt)obj.addReferenceLine('horizontal')); uibutton(toolGrid, ... 'Text', '添加垂直线', ... 'ButtonPushedFcn', @(src,evt)obj.addReferenceLine('vertical')); uibutton(toolGrid, ... 'Text', '标记数据点', ... 'ButtonPushedFcn', @(src,evt)obj.enablePointSelection()); uibutton(toolGrid, ... 'Text', '清除参考线', ... 'ButtonPushedFcn', @(src,evt)obj.clearReferenceLines()); uibutton(toolGrid, ... 'Text', '清除标记点', ... 'ButtonPushedFcn', @(src,evt)obj.clearDataPoints()); uibutton(toolGrid, ... 'Text', '吸附设置', ... 'ButtonPushedFcn', @(src,evt)obj.configureSnapRadius()); % === 启用坐标交互 (R2024a兼容) === try disableDefaultInteractivity(obj.axes); obj.axes.Interactions = [zoomInteraction, panInteraction]; axtoolbar(obj.axes, {'zoomin', 'zoomout', 'pan', 'restoreview'}); catch % 旧版本兼容 zoom(obj.axes, 'on'); pan(obj.axes, 'on'); end % === 鼠标回调设置 === obj.fig.WindowButtonDownFcn = @(src,evt)obj.onMouseDown(src,evt); obj.fig.WindowButtonMotionFcn = @(src,evt)obj.onMouseMove(src,evt); obj.fig.WindowButtonUpFcn = @(src,evt)obj.onMouseUp(src,evt); % === 修复1: 使用有效图标或移除图标 === try % 方案1: 使用MATLAB内置图标名称 obj.btnMultiPlot = uibutton(multiGrid, ... 'Text', '创建多图窗口', ... 'Icon', 'add', ... % MATLAB内置图标名称 'ButtonPushedFcn', @(src,evt)obj.createMultiPlot()); catch % 方案2: 创建简单的加号图标 iconData = zeros(16, 16, 3); % 创建16x16空白图像 iconData(8, 3:14, :) = 1; % 水平线 (白色) iconData(3:14, 8, :) = 1; % 垂直线 (白色) obj.btnMultiPlot = uibutton(multiGrid, ... 'Text', '创建多图窗口', ... 'Icon', iconData, ... % 直接使用图像数据 'ButtonPushedFcn', @(src,evt)obj.createMultiPlot()); end uibutton(multiGrid, 'Text', '添加选中项', ... 'ButtonPushedFcn', @(src,evt)obj.addToActiveMultiPlot(), ... 'Enable', 'off', ... 'Tag', 'addToMultiBtn'); obj.btnSaveCSV = uibutton(multiGrid, ... 'Text', '保存为CSV', ... 'ButtonPushedFcn', @(src,evt)obj.saveToCSV()); % === 底部按钮区 === btnPanel = uipanel(mainGrid, 'BorderType', 'none'); btnPanel.Layout.Row = 3; btnPanel.Layout.Column = [1, 3]; btnGrid = uigridlayout(btnPanel, [1, 4]); btnGrid.ColumnWidth = {'1x', '1x', '1x', '1x'}; btnGrid.Padding = [5, 10, 5, 10]; uibutton(btnGrid, 'Text', '清除图表', ... 'ButtonPushedFcn', @(src,evt)cla(obj.axes)); obj.btnPlotRefresh = uibutton(btnGrid, 'Text', '刷新数据', ... 'ButtonPushedFcn', @(src,evt)obj.plotAllData(), ... 'BackgroundColor', [0.3, 0.6, 1], ... 'FontColor', 'white'); uibutton(btnGrid, 'Text', '导出图表', ... 'ButtonPushedFcn', @(src,evt)obj.exportPlot(), ... 'Tag', 'exportPlotBtn'); uibutton(btnGrid, 'Text', '帮助', ... 'ButtonPushedFcn', @(src,evt)obj.showHelp(), ... 'Tag', 'helpBtn'); % 延迟初始绘图 drawnow; % 使用drawnow替代pause obj.plotAllData(); end function setSelectionMode(obj, mode) obj.selectionMode = mode; if strcmp(mode, 'single') obj.keyListbox.Multiselect = 'off'; % 单选时自动选择第一项 if ~isempty(obj.keyListbox.Items) obj.keyListbox.Value = obj.keyListbox.Items{1}; end else obj.keyListbox.Multiselect = 'on'; end obj.plotSelectedData(); end function plotAllData(obj) % === 安全检测 === if ~isvalid(obj.axes), return; end cla(obj.axes); keys = obj.dataMap.keys(); if isempty(keys) title(obj.axes, '无可用数据'); return; end for i = 1:length(keys) key = keys{i}; if isKey(obj.dataMap, key) data = obj.dataMap(key); if isempty(data) warning('键 "%s" 的数据为空,跳过绘图', key); continue; end if isrow(data), data = data'; end plot(obj.axes, data, 'DisplayName', key); end end if ~isempty(allchild(obj.axes)) legend(obj.axes, 'show', 'Interpreter', 'none'); else title(obj.axes, '无有效数据可显示'); end end function plotSelectedData(obj) if ~isvalid(obj.axes), return; end cla(obj.axes); selectedKeys = obj.keyListbox.Value; if isempty(selectedKeys), return; end % 统一转换为元胞数组 if ischar(selectedKeys) selectedKeys = {selectedKeys}; elseif isstring(selectedKeys) selectedKeys = cellstr(selectedKeys); end for i = 1:length(selectedKeys) key = selectedKeys{i}; if isKey(obj.dataMap, key) data = obj.dataMap(key); if isrow(data), data = data'; end plot(obj.axes, data, 'DisplayName', key); end end if ~isempty(selectedKeys) legend(obj.axes, 'show', 'Interpreter', 'none'); end end function saveToCSV(obj) [filename, pathname] = uiputfile('*.csv', '保存CSV文件'); if isequal(filename, 0) || isequal(pathname, 0), return; end fullPath = fullfile(pathname, filename); keys = obj.dataMap.keys(); maxLength = max(cellfun(@(k)numel(obj.dataMap(k)), keys)); T = table(); for i = 1:length(keys) key = keys{i}; % ===== 修复3: 确保列向量处理 ===== data = obj.dataMap(key); if isrow(data), data = data'; end data = data(:); % 强制转换为列向量 if length(data) < maxLength data = [data; nan(maxLength-length(data), 1)]; end T.(key) = data(1:maxLength); end writetable(T, fullPath); uialert(obj.fig, sprintf('数据已保存到:\n%s', fullPath), '保存成功', 'Icon', 'success'); end function createMultiPlot(obj) multiFig = uifigure('Name', '多图视图', ... 'Position', [300, 300, 1000, 600], ... 'CloseRequestFcn', @(src,evt)obj.onMultiPlotClose(src)); obj.multiPlotFigures(end+1) = multiFig; obj.updateAddButtonState(); multiGrid = uigridlayout(multiFig, [3, 1]); multiGrid.RowHeight = {50, '1x', '1x'}; multiGrid.RowSpacing = 10; % 控制区 ctrlPanel = uipanel(multiGrid, 'BorderType', 'none'); ctrlGrid = uigridlayout(ctrlPanel, [1, 6]); ctrlGrid.ColumnWidth = {120, '1x', 120, 120}; % === 修复2: 添加按钮的稳健图标处理 === try % 方案1: 使用内置图标 addBtn = uibutton(ctrlGrid, 'Text', '添加数据集', ... 'Icon', 'add', ... % MATLAB内置图标 'ButtonPushedFcn', @(src,evt)obj.addToMultiPlot(multiFig)); catch try % 方案2: 使用自定义图像文件 iconPath = fullfile(matlabroot, 'toolbox', 'matlab', 'icons', 'addicon.gif'); if exist(iconPath, 'file') addBtn = uibutton(ctrlGrid, 'Text', '添加数据集', ... 'Icon', iconPath, ... 'ButtonPushedFcn', @(src,evt)obj.addToMultiPlot(multiFig)); else % 方案3: 创建替代文本按钮 addBtn = uibutton(ctrlGrid, 'Text', '+ 添加数据集', ... 'BackgroundColor', [0.1, 0.7, 0.2], ... 'FontColor', 'white', ... 'FontWeight', 'bold', ... 'ButtonPushedFcn', @(src,evt)obj.addToMultiPlot(multiFig)); end catch % 方案4: 纯文本按钮 addBtn = uibutton(ctrlGrid, 'Text', '添加数据集', ... 'ButtonPushedFcn', @(src,evt)obj.addToMultiPlot(multiFig)); end end % 数据选择下拉框 dataDropdown = uidropdown(ctrlGrid, 'Items', keys(obj.dataMap), ... 'Tag', 'multiPlotDropdown'); uibutton(ctrlGrid, 'Text', '清除所有', ... 'ButtonPushedFcn', @(src,evt)obj.clearMultiPlot(multiFig)); uibutton(ctrlGrid, 'Text', '保存视图', ... 'ButtonPushedFcn', @(src,evt)obj.saveMultiPlot(multiFig)); % 列表区 listPanel = uipanel(multiGrid, 'Title', '已选数据集'); listGrid = uigridlayout(listPanel, [1,1]); listbox = uilistbox(listGrid, 'Items', {}, ... 'Multiselect', 'on'); % 绘图区 plotPanel = uipanel(multiGrid, 'Title', '多图叠加显示'); plotGrid = uigridlayout(plotPanel, [1,1]); ax = uiaxes(plotGrid); hold(ax, 'on'); grid(ax, 'on'); % 存储句柄 multiFig.UserData = struct(... 'axesHandle', ax, ... 'listboxHandle', listbox, ... 'dropdownHandle', dataDropdown); end function updateAddButtonState(obj) addBtns = findobj(obj.fig, 'Tag', 'addToMultiBtn'); if ~isempty(obj.multiPlotFigures) && all(isvalid(obj.multiPlotFigures)) set(addBtns, 'Enable', 'on'); else set(addBtns, 'Enable', 'off'); % ===== 修复6: 清理无效引用 ===== obj.multiPlotFigures(~isvalid(obj.multiPlotFigures)) = []; end end function addToActiveMultiPlot(obj) if isempty(obj.multiPlotFigures) || ~any(isvalid(obj.multiPlotFigures)) uialert(obj.fig, '请先创建多图窗口', '无活动窗口'); return; end activeFig = obj.multiPlotFigures(end); if isvalid(activeFig) obj.addToMultiPlot(activeFig); end end function addToMultiPlot(obj, multiFig) % ===== 修复5: 增加安全检测 ===== if ~isvalid(multiFig) || ~isfield(multiFig.UserData, 'listboxHandle') return; end ud = multiFig.UserData; selectedKeys = obj.keyListbox.Value; if isempty(selectedKeys), return; end if ischar(selectedKeys) selectedKeys = {selectedKeys}; end currentItems = ud.listboxHandle.Items; if isempty(currentItems) currentItems = {}; end newItems = setdiff(selectedKeys, currentItems); if ~isempty(newItems) ud.listboxHandle.Items = [currentItems; newItems(:)]; obj.updateMultiPlot(multiFig); end end function updateMultiPlot(obj, multiFig) % ===== 修复5: 增加安全检测 ===== if ~isvalid(multiFig) || ~isfield(multiFig.UserData, 'axesHandle') return; end ud = multiFig.UserData; cla(ud.axesHandle); selectedKeys = ud.listboxHandle.Items; if isempty(selectedKeys), return; end if ischar(selectedKeys) selectedKeys = {selectedKeys}; end for i = 1:length(selectedKeys) key = selectedKeys{i}; if isKey(obj.dataMap, key) data = obj.dataMap(key); if isrow(data), data = data'; end plot(ud.axesHandle, data, 'DisplayName', key); end end legend(ud.axesHandle, 'show', 'Interpreter', 'none'); end function clearMultiPlot(obj, multiFig) if ~isvalid(multiFig), return; end if isfield(multiFig.UserData, 'axesHandle') && isvalid(multiFig.UserData.axesHandle) cla(multiFig.UserData.axesHandle); legend(multiFig.UserData.axesHandle, 'off'); end if isfield(multiFig.UserData, 'listboxHandle') && isvalid(multiFig.UserData.listboxHandle) multiFig.UserData.listboxHandle.Items = {}; end end % ===== 新增缩放功能方法 ===== function setZoomMode(obj, mode) obj.zoomMode = mode; % 更新按钮状态 for i = 1:3 if mode == (i-1) obj.zoomButtons(i).BackgroundColor = [0.7, 0.9, 1]; obj.zoomButtons(i).FontWeight = 'bold'; else obj.zoomButtons(i).BackgroundColor = [0.96, 0.96, 0.96]; obj.zoomButtons(i).FontWeight = 'normal'; end end % R2024a兼容缩放设置 try zoomHandle = zoom(obj.fig); set(zoomHandle, 'Motion', 'both', 'Enable', 'on'); switch mode case 0 % 自由缩放 set(zoomHandle, 'Motion', 'both'); case 1 % 水平缩放 set(zoomHandle, 'Motion', 'horizontal'); case 2 % 垂直缩放 set(zoomHandle, 'Motion', 'vertical'); end catch % 旧版本备用方案 zoom(obj.axes, 'on'); end end % ===== 新增参考线功能方法 ===== function addReferenceLine(obj, orientation) % 获取当前轴范围 xlims = obj.axes.XLim; ylims = obj.axes.YLim; % 创建参考线(修复变量名冲突) switch orientation case 'horizontal' y = mean(ylims); % 默认放在中间 refLine = line(obj.axes, xlims, [y, y], ... % 变量名改为 refLine 'Color', [0, 0.6, 0], 'LineWidth', 1.5, ... 'PickableParts', 'visible', ... 'Tag', 'HReferenceLine'); % 添加数据标签(兼容 R2024a) try dt = datatip(refLine, 'DataIndex', 1); dt.Location = 'northwest'; catch text(obj.axes, xlims(1), y, sprintf('Y=%.4f', y), ... 'Color', [0, 0.6, 0], 'FontWeight', 'bold'); end case 'vertical' x = mean(xlims); refLine = line(obj.axes, [x, x], ylims, ... % 变量名改为 refLine 'Color', [0.8, 0, 0.2], 'LineWidth', 1.5, ... 'PickableParts', 'visible', ... 'Tag', 'VReferenceLine'); % 添加数据标签(兼容 R2024a) try dt = datatip(refLine, 'DataIndex', 1); dt.Location = 'northeast'; catch text(obj.axes, x, ylims(2), sprintf('X=%.4f', x), ... 'Color', [0.8, 0, 0.2], 'FontWeight', 'bold'); end end % 存储线条对象(使用新变量名) obj.refLines(end+1) = refLine; % 开启拖拽功能 set(refLine, 'ButtonDownFcn', @(src,evt)obj.startDrag(src)); end function startDrag(obj, src) obj.currentDraggingLine = src; % 获取当前线段的坐标数据 obj.originalPosition = get(src, {'XData', 'YData'}); end function clearReferenceLines(obj) delete(obj.refLines); obj.refLines = matlab.graphics.primitive.Line.empty; end % ===== 新增数据点标记方法 ===== function enablePointSelection(obj) % 设置标记模式 obj.pointSelectionMode = true; set(obj.fig, 'Pointer', 'crosshair'); uialert(obj.fig, '点击图中位置标记数据点', '标记模式', 'Icon', 'info'); end function markDataPoint(obj, x, y) % 查找最近的数据点 [closestX, closestY, dataKey, pointIndex] = obj.findNearestDataPoint(x, y); % 创建标记点 marker = scatter(obj.axes, closestX, closestY, 100, ... 'Marker', 'd', 'MarkerEdgeColor', 'k', ... 'MarkerFaceColor', [1, 0.8, 0.2], ... 'LineWidth', 1.5, ... 'Tag', 'DataMarker'); % 添加数据标签 dt = datatip(marker, 'DataIndex', 1); dt.FontSize = 10; dt.FontWeight = 'bold'; dt.String = {sprintf('数据集: %s', dataKey), ... sprintf('索引: %d', pointIndex), ... sprintf('值: %.4f', closestY)}; % 存储标记点信息 obj.dataPoints(end+1) = struct(... 'x', closestX, ... 'y', closestY, ... 'handle', marker, ... 'index', pointIndex, ... 'dataKey', dataKey); end function clearDataPoints(obj) for i = 1:length(obj.dataPoints) if isvalid(obj.dataPoints(i).handle) delete(obj.dataPoints(i).handle); end end obj.dataPoints = struct('x', {}, 'y', {}, 'handle', {}, 'index', {}); end function configureSnapRadius(obj) answer = inputdlg('设置吸附半径 (0.01-0.1):', '吸附灵敏度', 1, {num2str(obj.snapRadius)}); if ~isempty(answer) newRadius = str2double(answer{1}); if ~isnan(newRadius) && newRadius > 0 && newRadius <= 0.1 obj.snapRadius = newRadius; end end end % ===== 新增吸附查找方法 ===== function [closestX, closestY, dataKey, pointIndex] = findNearestDataPoint(obj, x, y) % 获取当前轴范围 xRange = range(obj.axes.XLim); yRange = range(obj.axes.YLim); % 初始化最近点变量 minDistance = inf; closestX = NaN; closestY = NaN; dataKey = ''; pointIndex = 0; % 遍历所有可见数据 visibleLines = findobj(obj.axes, 'Type', 'line', 'Visible', 'on'); for i = 1:length(visibleLines) lineData = visibleLines(i); xData = lineData.XData; yData = lineData.YData; % 仅处理有显示名称的数据集 if isempty(lineData.DisplayName) || strcmp(lineData.DisplayName, '') continue; end % 计算点到数据集的归一化距离 normDistances = sqrt(... ((xData - x)/xRange).^2 + ... ((yData - y)/yRange).^2); % 查找最小距离点 [dist, idx] = min(normDistances); % 检查是否在吸附半径内 if dist < obj.snapRadius && dist < minDistance minDistance = dist; closestX = xData(idx); closestY = yData(idx); dataKey = lineData.DisplayName; pointIndex = idx; end end % 如果没有找到吸附点,使用原始坐标 if isnan(closestX) closestX = x; closestY = y; dataKey = '手动标记'; pointIndex = 0; end end % ===== 新增鼠标事件处理方法 ===== function onMouseDown(obj, src, event) % 获取当前点坐标 cp = obj.axes.CurrentPoint(1,1:2); x = cp(1); y = cp(2); % 检查是否在标记模式 if isfield(obj, 'pointSelectionMode') && obj.pointSelectionMode obj.markDataPoint(x, y); obj.pointSelectionMode = false; set(obj.fig, 'Pointer', 'arrow'); return; end % 检查是否点击了参考线 hitObject = hittest(obj.fig); if any(hitObject == obj.refLines) obj.currentDraggingLine = hitObject; obj.originalPosition = get(hitObject, {'XData', 'YData'}); return; end end function onMouseMove(obj, src, event) % 添加两个额外参数占位 % 处理参考线拖拽 if ~isempty(obj.currentDraggingLine) && isvalid(obj.currentDraggingLine) cp = obj.axes.CurrentPoint(1,1:2); x = cp(1); y = cp(2); tag = get(obj.currentDraggingLine, 'Tag'); if strcmp(tag, 'HReferenceLine') % 更新水平线位置 set(obj.currentDraggingLine, 'YData', [y, y]); % 更新数据标签 dt = findobj(obj.currentDraggingLine, 'Type', 'datatip'); if ~isempty(dt) dt.Position = [mean(obj.axes.XLim), y]; dt.String = sprintf('Y = %.4f', y); end elseif strcmp(tag, 'VReferenceLine') % 更新垂直线位置 set(obj.currentDraggingLine, 'XData', [x, x]); % 更新数据标签 dt = findobj(obj.currentDraggingLine, 'Type', 'datatip'); if ~isempty(dt) dt.Position = [x, mean(obj.axes.YLim)]; dt.String = sprintf('X = %.4f', x); end end end end % ===== 新增onMouseUp方法 ===== function onMouseUp(obj, src, event) % 释放当前拖拽的参考线 if ~isempty(obj.currentDraggingLine) && isvalid(obj.currentDraggingLine) obj.currentDraggingLine = []; % 更新参考线标签位置 obj.updateReferenceLineLabels(); end % 清除点标记模式 obj.pointSelectionMode = false; set(obj.fig, 'Pointer', 'arrow'); end % ===== 辅助方法:更新参考线标签 ===== function updateReferenceLineLabels(obj) for i = 1:length(obj.refLines) tag = obj.refLines(i).Tag; if strcmp(tag, 'HReferenceLine') % 更新水平线标签 y = mean(obj.refLines(i).YData); textObjs = findobj(obj.refLines(i), 'Type', 'text'); if ~isempty(textObjs) textObjs.String = sprintf('Y=%.4f', y); textObjs.Position(2) = y; end elseif strcmp(tag, 'VReferenceLine') % 更新垂直线标签 x = mean(obj.refLines(i).XData); textObjs = findobj(obj.refLines(i), 'Type', 'text'); if ~isempty(textObjs) textObjs.String = sprintf('X=%.4f', x); textObjs.Position(1) = x; end end end end function onMultiPlotClose(obj, fig) if isvalid(fig) delete(fig); end % ===== 修复6: 完全移除引用 ===== validIdx = isvalid(obj.multiPlotFigures) & (obj.multiPlotFigures ~= fig); obj.multiPlotFigures = obj.multiPlotFigures(validIdx); obj.updateAddButtonState(); end % 预留接口保持不变 function exportPlot(obj) end function showHelp(obj) end function saveMultiPlot(obj, fig) end end end 出现了参考线,但是无法拖动,而且无法自由的选择参考线出现的位置 解决代码中存在的问题,写出更新后的完整代码!!!
最新发布
10-11
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值