How can I use ginput in app designer?
    69 visualizaciones (últimos 30 días)
  
       Mostrar comentarios más antiguos
    
    Jaime Serrano
 el 4 de Abr. de 2018
  
    
    
    
    
    Comentada: Kristoffer Walker
 el 5 de Nov. de 2024
            I would like to select a range of points from one particular UIAxes in my app.
I have tried to use ginput ([x,y=ginput]), but the applications prompts an additional empty plot to select the range of points. How can I point an specific UIAxes?
Kind Regards
2 comentarios
  Wonsup Lee
 el 17 de Jul. de 2020
				I got success by referring to this answer: https://kr.mathworks.com/matlabcentral/answers/506032-how-do-i-select-a-point-on-matlab-uiaxes-and-then-get-data-for-it
Just use drawpoint function instead of drawrectangle.
One line in callback function or a main code.
[x, y] = selectDataPoints(app, app.figArea);
And, create a function.
function [x, y] = selectDataPoints(~, ax)
    roi = drawpoint(ax);
    x = roi.Position(1);
    y = roi.Position(2);
end
  Kristoffer Walker
 el 5 de Jun. de 2024
				
      Movida: Adam Danz
    
      
 el 5 de Jun. de 2024
  
			The workaround for lack of ginput support for UIAxes is alarming.  I've been constantly frustrated by this lack of attention, and by my lack of an ability to get on the same wavelength as the AppDesigner developers such that I can use the workarounds efficiently.  I love AppDesigner in general, but the lack of basic interactivity with UIAxes is very frustrating.  I want mouse clicks, key presses, and more.  And I am expecting them to show up in AppDesigner's UI interface as options.
Respuesta aceptada
  Adam Danz
    
      
 el 4 de Oct. de 2020
        
      Editada: Adam Danz
    
      
 el 4 de Oct. de 2020
  
      ginput is now supported in AppDesigner starting in r2020b
We still don't have an option to specify the target figure handle in ginput so you have to make the App's figure handle visible so ginput doesn't land on the wrong figure or create a new figure.  
The example below is a callback function that responds to a button press and does the following:
- Test that user is using r2020b or later; if not, throw error.
 - Save current state of the app figure handle visibility.
 - Change the app figure handle visibility so that it's accessible to the callback function.
 - Make app figure current
 - Call ginput
 - Return the original figure handle visibility state.
 
% Button pushed function: Button
function ButtonPushed(app, event)
    % Check Matlab version, throw error if prior to r2020b
    assert(~verLessThan('Matlab', '9.9'), 'ginput not supported prior to Matlab r2020b.')
    % Set up figure handle visibility, run ginput, and return state
    fhv = app.UIFigure.HandleVisibility;        % Current status
    app.UIFigure.HandleVisibility = 'callback'; % Temp change (or, 'on') 
    set(0, 'CurrentFigure', app.UIFigure)       % Make fig current
    [x,y,b] = ginput(1);                        % run ginput
    app.UIFigure.HandleVisibility = fhv;        % return original state
end
See also
6 comentarios
  Adam Danz
    
      
 el 16 de Dic. de 2020
				I agree.   You can create a service request > technical support, to make this suggestion.
Más respuestas (6)
  Jon Nykiel
      
 el 18 de Jun. de 2019
        Unfortunately, ginput is not supported within appdesigner. However, as of R2019A, the CurrentPoint property can be used within a WindowButtonDown function to get the coordinates of a button click within UIAxes.
Simple example: 
function UIFigureWindowButtonDown(app, event)
            temp = app.UIAxes.CurrentPoint; % Returns 2x3 array of points
            loc = [temp(1,1) temp(1,2)]; % Gets the (x,y) coordinates
end    
1 comentario
  Richard Saumarez
      
 el 18 de Jun. de 2019
        I agree about the comments on appDesigner
After a lot of work, and bending one's foot round one's ear, one can write a GUI that has most of the functionality written in Visual stdio or Fortran.  But it seems counterintuitive and everything that one would like to do, and would think is being easy,  is "not supported".
There is no doubt in my mind that appDesigner needs more functionality if one is going to write an artistic, commercially useful, GUI that is not simply knobs and sliders.  Apart from the difficulty in getting the mouse position, one desperately needs to be able to draw on the uppermost layer of the GUI, not in a plot, but in the container itself.
I may be being unfair, and this may be possible, but finding one's way around Matlab documentation, apart from the most basic aspects, is really difficult.
0 comentarios
  HM
 el 31 de Ag. de 2018
        I found this thread because I was looking for the same thing. We definitely need a 'ginput' function that works within a UIFigure.
However, I did find a workaround: invoke a new 'normal' matlab figure with 'figure' (e.g. MyFigure = figure;) plot on that figure any plots/graphics that you have plotted on your UIFigure (any relevant graphics that you need on there to be able to click relative to). Note, use the traditional plot() command, rather than the plot(app.UIFigure, ) command. Then use the ginput function with that figure. (e.g. MyPoints = ginput;) then delete the figure, and use the recorded values as desired. (e.g. delete(MyFigure); )
This actually worked well for me, as the 'pop-up' figure is larger than my UIFigure, allowing for more accurate mouse clicking.
Hope that helps. Cheers, Hugh.
0 comentarios
  chrisw23
      
 el 18 de En. de 2019
        
      Editada: chrisw23
      
 el 18 de En. de 2019
  
      You can define a ButtonDownFcn callback that delivers 'Hit' event data for axes, which has an IntersectionPoint property. This is also valid for lines, but not for ie. the MainFigure  (MouseData event only).
This works fine although the AppDesigner doesn't support callback properties for Axes ( tested with SubPlot with Panel Parent in R2018b ).
app.myAx = subplot(2,1,1,'Parent',app.Panel);  % create plot
app.myAx.ButtonDownFcn = createCallbackFcn(app, @app.getMousePosition, true);
function getMousePosition(app,source,event)
    switch event.EventName
        case 'Hit'
            % Properties: Btn/IntersectionPoint/Src/Evnt
            posData = event.IntersectionPoint; % to be used for calc
        case 'MouseData'
            % Properties: Src/EvntName
    end
end
Hope it helps
Christian
2 comentarios
  Rajpal Singh
 el 18 de Mayo de 2019
				Is there any solution for app designer also to get points from  multiple line plot.
I want draw a  staright child line on parent line by clicking on it.
  Richard Saumarez
      
 el 17 de Jun. de 2019
				Brilliant!
I've been tearing my hair out trying to solve this.
App designer really need a simple to use mouse position function that isn't as tortuous as this.
  Birdman
      
      
 el 4 de Abr. de 2018
        You can't. If you check the documentation of ginput, you will see it can not take a predefined axes as an input argument:
There might be custom written functions for that though, you just have to google it.
2 comentarios
  Mathias Hell
 el 12 de Oct. de 2019
				That is not true. I was working on a Matlab GUI with GUIDE and used the ginput function to select several points on the predefined axes and it worked perfectly. However, when I use the function in the same way in the Maltab App Designer I encounter the described problem.
function setapointbutton_Callback(hObject, eventdata, handles)
handles = guidata(hObject);
zoom(handles.ax,'off');
pan(handles.ax,'off');
while(1)    
    handles.length = length(handles.point_x);
    [handles.point_x(handles.length+1,1) ,handles.point_y(handles.length+1,1)] = ginput(1);
    key = get(gcf,'selectiontype');
    if strcmp(key,'alt')
        handles.point_x(handles.length+1,:) = [];
        handles.point_y(handles.length+1,:) = [];
        break;
    else 
        handles.grafikhandle_points(1, handles.length+1) = plot(handles.point_x(handles.length+1,1),handles.point_y(handles.length+1,1),'bo');
        handles.grafikhandle_points(1, handles.length+1).UIContextMenu = handles.c1;
    end
end
  Walter Roberson
      
      
 el 18 de Jul. de 2020
				I just looked at the source code. There is no way to pass a figure or an axes to ginput(). Birdman was correct that there is no way to select which figure or axes that ginput() operates on.
ginput() uses gcf(), which will only find traditional figures. If you have no traditional figure that is active then ginput() will open a new figure. So ginput() can work in GUIDE, but it cannot work on uifigures.
  Vlad Atanasiu
      
 el 2 de Oct. de 2020
        Here is an illustration of how to simulate ginput with uifigures (App Designer, R2020b).
function uiginput
% Get coordinates of clicked point on image in uifigure and uiaxes.
% Remove datatips by pressing "Escape".
% Create uifigure
fig = uifigure;
fig.WindowKeyPressFcn = @onKeyPress;
% Create uiaxes
ax = uiaxes(fig);
ax.PickableParts = 'visible';
ax.HitTest = 'on';
% Display classic image in uiaxes
I = imread('membrane.png'); % 100 x 86 px
im = imshow(I,'Parent',ax);
im.ButtonDownFcn = @onClickImage;
    % Capture clicks on uiaxes
    function [x, y] = onClickImage(~,~)
        % Set the image to allow clicks to pass through it
        im.PickableParts = 'none';
        im.HitTest = 'off';
        % Get coordinates of clicked point from uiaxes
        x = ax.CurrentPoint(1);
        y = ax.CurrentPoint(3);
        % Revert above changes to image properties
        im.PickableParts = 'visible';
        im.HitTest = 'on';
        % Compute integer pixel coordinates
        if x < 1
            % Correct a location error of one pixel
            % between axes and image coordinates
            x = 1;
        else
            x = floor(x);
        end
        if y < 1
            y = 1;
        else
            y = ceil(y);
        end
        % Delete previous datatips, if any
        try
            dt = findall(fig,'Type','datatip');
            if ~isempty(dt)
                delete(dt)
            end
        catch
            %
        end
        % Display pixel coordinates on datatip
        % (The origin is at the top left of the image)
        message = ['x ',num2str(x),', y ',num2str(y)];
        datatip(im,x,y);
        im.DataTipTemplate.DataTipRows(1).Label = message;
        im.DataTipTemplate.DataTipRows(1).Value = [x,y];
        im.DataTipTemplate.DataTipRows(2).Label = '';
        im.DataTipTemplate.DataTipRows(2).Value = '';
    end
    % Capture key presses
    function onKeyPress(~, event)
        % Which kwy was pressed?
        clickType = event.Key;
        % remove datatip
        if strcmp(clickType,'escape')
            try
                dt = findall(fig,'Type','datatip');
                if ~isempty(dt)
                    delete(dt)
                end
            catch
                %
            end
        end
    end
end
6 comentarios
  Vlad Atanasiu
      
 el 4 de Oct. de 2020
				
      Editada: Vlad Atanasiu
      
 el 4 de Oct. de 2020
  
			> you can use datacursormode starting in r2020a
Yes, I was there too, using datatips, but datatips are not substitutes for contextmenu. In particular the content is editable, which might not be desirable; once you edited it other datatips copy the said content. Implementing clickable links via datatips is also difficult, since when you click the datatip it opens for editing. Moreover, datatip have predefined content which becomes visible when the datatips are activated and there is a visible latency between the display of the initial content and the dynamical content that replaces it.
> That's not quite correct. ginput returns coordinates in axis units (see documentation).
Yes, but what if need to get image coordinates without ginput (= two clicks)? [Which is a topic diverging from the initial question in this thread, so we might want to move the discussion to a new thread.]
A fundamental problem is that of Matlab transitioning from Java to JavaScript-based interfaces and a doubling of functions with partially overlapping capabilities and incompatibilies.
  Vlad Atanasiu
      
 el 4 de Oct. de 2020
				
      Editada: Vlad Atanasiu
      
 el 4 de Oct. de 2020
  
			Here is another use case involving getting image coordinates. You display a set of images as imtile, then click on one of them to popup a tooltip with metadata, such as label, then click on the tooltip to display the single image.
I didn't find any satisfactory solution, so I abandoned imtile. Instead I displayed uiimages in uigridlayout, with the metadata in the Tooltip property and the hyperlinks in the ImageClickedFcn callback. I still have the minor visual issue that gaps appear between rows or columns because the gridlayout manager adapts to the aspect ratio of its parent container.
[This comment is also veering towards off-topic, but it explains the wider context of different solutions.]
Ver también
Categorías
				Más información sobre Data Exploration en Help Center y File Exchange.
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!