MATLAB addlistener с дополнительными аргументами в графическом интерфейсе - PullRequest
0 голосов
/ 04 сентября 2018

Я пишу MATLAB GUI, у которого есть оси для отображения изображения с помощью кнопки. Я также использую impixelinfoval, чтобы показать пиксельные координаты расположения мыши следующим образом:

h = imshow('hestain.png', 'Parent', handles.axes1);
hp = impixelinfoval(gcf, h);

Я могу успешно добавить слушатель к дескриптору impixelinfoval без аргумента, переданного функции обратного вызова:

addlistener(hp, 'String', 'PostSet', @mycallback) % Works

Однако я пытаюсь передать два аргумента в функцию обратного вызова следующим образом, и мне не удалось передать их в функцию. Мне нужно handles для хранения переменной, вычисленной в функции обратного вызова, а также hObject, чтобы иметь возможность выполнить guidata(hObject, handles), чтобы у меня был доступ к новой переменной во всем графическом интерфейсе.

addlistener(hp, 'String', 'PostSet', @mycallback1(hObject, handles))  % Does not work

Может ли кто-нибудь помочь мне с этой проблемой?

Ниже приводится описание всего MWE для проверки этой проблемы:

function varargout = untitled(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @untitled_OpeningFcn, ...
                   'gui_OutputFcn',  @untitled_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end


function untitled_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);

function varargout = untitled_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output;


% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
h = imshow('hestain.png', 'Parent', handles.axes1);
hp = impixelinfoval(gcf, h);
addlistener(hp, 'String', 'PostSet', @mycallback) % Works
% addlistener(hp, 'String', 'PostSet', @mycallback1(hObject, handles)) % Does not work. I would like to pass both hObject and handles to mycallback function.


function mycallback(src, evt)
disp(evt.AffectedObject.String)

function mycallback1(src, evt, hObject, handles)
disp(evt.AffectedObject.String)
% Create a variable and store it in the handles
handles.pixelcoord = evt.AffectedObject.String;
% Update handles
guidata(hObject, handles)

1 Ответ

0 голосов
/ 04 сентября 2018

Слушатель по умолчанию захочет передать 2 параметра по умолчанию в соответствии с вашим примером, который работает:

addlistener(hp, 'String', 'PostSet', @mycallback() )

Вы должны заметить, что в вашей функции есть 2 входа:

function mycallback ( src, event )
   ...
end

То, что вы пытаетесь сделать, это либо:

  1. Добавить 2 дополнительных аргумента
  2. Заменить 2 аргумента по умолчанию на другой 2.

Вы делаете это, контролируя функцию обратного вызова:

addlistener(hp, 'String', 'PostSet', @(src,evt)mycallback1(src, evt, hObject, handles))

или

addlistener(hp, 'String', 'PostSet', @(src,evt)mycallback1(hObject, handles))

Приведенные выше строки фиксируют обратные вызовы по умолчанию src и evt, и первая передает их вашему обратному вызову с вашими дополнительными переменными, другая - нет.

edit Мой ответ был сосредоточен на том, как вызвать слушателя, у меня нет набора инструментов для обработки изображений, поэтому я не могу создать код, который использует функцию impixelinfoval.

Поскольку ваш код сам по себе не запускается, я создал небольшой пример ниже, который показывает вам, как добавить прослушиватели, которые реагируют, когда установлено свойство строки (в данном случае заголовок оси), оно запускается самостоятельно, поэтому Вы должны быть в состоянии запустить его и посмотреть, как он работает.

function untitled
 %%
 % create a figure
  h = figure;
  % create an axes
  ax = axes ( 'parent', h );
  % create a variable which we will plot
  p = peaks(50);
  % plot the variable
  imagesc ( p, 'parent', ax );
  % createa some initial title, x and y lables
  t = title ( ax, 'Title' );
  x = xlabel ( ax, 'X Label' );
  y = ylabel ( ax, 'Y Label' );
  %  add a callback to run when the mouse moves.
  h.WindowButtonMotionFcn = @(a,b)moveMouse (ax, t);
  % add listeners which are triggered after the title has been set
  %  this listener passes the standard callbacks and some extras, namely
  %    the handles of the title and the y label
  addlistener ( t, 'String', 'PostSet', @(h,evt)mycallback1(h,evt,t,y) )
  % this listener only passes the handle to the title and the x label
  addlistener ( t, 'String', 'PostSet', @(h,evt)mycallback(t,x) )
end
function moveMouse ( ax, t )
  % update the title of the axes for
  t.String = sprintf ( 'current point %.1f,%.1f', ax.CurrentPoint(1,1:2) );
end
function mycallback ( t, x )
  % udpate the x label string
  x.String = sprintf ( 'X Label -> title value: %s', t.String );
end
function mycallback1 ( h, event, t, y )
  % update the y label string
  y.String = sprintf ( 'Y Label -> title value: %s', t.String );
end

Этот графический интерфейс создан из кода (не руководства).

Это работает путем обновления названия осей, когда мышь перемещается, чтобы указать текущую точку. Я добавил 2 слушателей, которые обновляют строки меток X и Y после того, как заголовок был установлен.

Зная, как добавить слушателей, вы сможете использовать эту теорию в своем собственном коде, и это может подчеркнуть, какие у вас есть оставшиеся ошибки.

ваше сообщение об ошибке в комментариях ниже

addlistener(hp, 'String', 'PostSet', @(source, event, hObject, handles)myImageMagnifier3(source, event, hObject, handles))

Я подозреваю, что это должно быть:

addlistener(hp, 'String', 'PostSet', @(source, event)myImageMagnifier3(source, event, hObject, handles))

как в моем исходном примере.

...