#matlab #tooltip #overlay #matlab-figure #mouseover
#matlab #всплывающая подсказка #наложение #matlab-рисунок #наведение курсора мыши
Вопрос:
У меня есть рисунок с двумя или более линиями. С этими строками связана дополнительная важная информация, например, сколько точек данных было усреднено для создания линии и т.д. Я хотел бы получить доступ к этой информации на моем рисунке.
Я подумал, что хорошим решением для этого было бы, если бы вы могли навести курсор мыши на строку и получить эту расширенную информацию.
Однако поиск всплывающих подсказок / наложений / наведения курсора мыши на рисунки, казалось, не был плодотворным.
Пример:
figure; hold on;
plot(1:10,rand(10,1))
plot(1:10,rand(10,1))
% additional info
plot_1_info.name = 'Alice';
plot_2_info.name = 'Bob';
plot_1_info.age = 24;
plot_2_info.age = 12;
Есть хорошие решения или лучшие подходы для этого?
Комментарии:
1. 2 вопроса: 1) Какую версию MATLAB вы используете? 2) Подходят ли вам UIFigures?
2. 1) R2018b Update3, новейший стабильный, если я прав 2) Я не знаю о них, я думаю, но я бы предпочел максимально простой подход
3. 1) Новейшая стабильная версия — R2019a 😉 2) Это так же просто … скорее вопрос совместимости с существующим кодом / рисунками (uifigures — это «новые» рисунки).
4. оба ответа потрясающие, выбрал ответ Вулфи для обратной совместимости, оба должны быть правильными
Ответ №1:
Вы можете изменить поведение курсора данных, этот параметр обладает хорошей обратной совместимостью (я тестировал приведенный ниже в R2017b, аналогичный использовался ранее в 15b).
Подробности смотрите в моих комментариях:
% Create some data
x = (1:2:20).';
y = rand(10,1);
name = { 'Alice'; 'Alice'; 'Alice'; 'Alice'; 'Bob'; 'Bob'; 'Bob'; 'Chris'; 'Chris'; 'Chris' };
age = [ 24; 24; 24; 24; 12; 12; 12; 17; 17; 17 ];
% Put it in a table, so we have it all together for indexing as plot data
tbl = table( x, y, name, age );
% Create the plot, assign the UserData property to the plot object
f = figure;
plt = plot( x, y );
plt.UserData = tbl;
% Hijack the Data Cursor update callback so we can inject our own info
dcm = datacursormode( f );
set( dcm, 'UpdateFcn', @onDataCursor );
% Function which returns the text to be displayed on the data cursor
function txt = onDataCursor( ~, evt )
% Get containing figure
f = ancestor( evt.Target, 'figure' );
% Get the index within the original data
idx = getfield( getCursorInfo( datacursormode( f ) ), 'DataIndex' );
% The original data is stored in the UserData property
data = evt.Target.UserData;
% Each element of the cell array is a new line on the cursor
txt = { sprintf( 'X: %g', data.x(idx) ), ...
sprintf( 'Y: %g', data.y(idx) ), ...
sprintf( 'Name: %s', data.name{idx} ), ...
sprintf( 'Age: %g', data.age(idx) ) };
end
Вывод:
Примечание: Я нигде не рассматривал случай, когда имеется более одной подсказки курсора данных. Вы можете легко реализовать цикл idx
в обратном вызове, чтобы справиться с этим, я оставляю это как упражнение.
Этот подход действительно гибкий. Например, если бы у нас было 3 строки (по одной на «человека»), то у каждой из них могла бы быть своя UserData
структура, и нам не нужно повторять всю информацию в строках таблицы.
A = struct( 'X', 1:4, 'Y', rand(1,4), 'Name', 'Alice', 'Age', 24 );
B = struct( 'X', 1:3, 'Y', rand(1,3), 'Name', 'Bob', 'Age', 12 );
C = struct( 'X', 1:3, 'Y', rand(1,3), 'Name', 'Chris', 'Age', 17 );
f = figure; hold on;
plt = plot( A.X, A.Y ); plt.UserData = A;
plt = plot( B.X, B.Y ); plt.UserData = B;
plt = plot( C.X, C.Y ); plt.UserData = C;
% ... Now the struct fields can be accessed from the callback
Комментарии:
1. Стоит упомянуть, что в R2019a настройка datatips была значительно упрощена .
2. @Dev-iL Не стесняйтесь публиковать ответ, у меня есть только R2017b для тестирования, а в OP нет R2019a.
3. спасибо за этот ответ, я попробую. @Dev-iL: Я обновляю прямо сейчас, пожалуйста, опубликуйте свой ответ 🙂
Ответ №2:
Используя новую систему настройки подсказок данных, представленную в R2019a, мы можем сделать следующее:
figure(); hP = plot(1:10,rand(10,1),1:10,rand(10,1));
nPts = cellfun(@numel, {hP.XData});
hP(1).DataTipTemplate.DataTipRows(end 1) = dataTipTextRow('Name', repmat("Alice",nPts(1),1) );
hP(1).DataTipTemplate.DataTipRows(end 1) = dataTipTextRow('Age', repmat(12, nPts(1),1) );
hP(2).DataTipTemplate.DataTipRows(end 1) = dataTipTextRow('Name', repmat("Bob", nPts(2),1) );
hP(2).DataTipTemplate.DataTipRows(end 1) = dataTipTextRow('Age', repmat(24, nPts(2),1) );
% (Of course the above can be organized in a nicer way using a function)
Что дает:
Обратите внимание, что «указатель мыши на данные» имеет черный текст, в то время как «указатель мыши на данные» имеет синий текст — это поведение по умолчанию.
Комментарии:
1. Я думаю, что понимаю сценарий, но он довольно сложный. Я полагаю, используя мой пример, я мог бы пойти на
hP=findall(gcf,'type','axes')
, и это сработало бы так же?2. Почти —
hP=findall(gcf,'type','Line')
.3. Не могли бы вы добавить / отредактировать, что необходимо преобразовать
char
вstring
, чтобы это работало с Алисой и Бобом?4. для меня это оказалось самым простым решением