AppDesigner: Getting a UIAxes' enableDefa​ultInterac​tivity to work with a UIFigure's WindowButtonDownFcn?

7 visualizaciones (últimos 30 días)
Dear all,
I would greatly appreciate any help with the following problem I am encountering. I will try to describe everything as clear as possible.
My Goal:
I am trying to create an app in AppDesigner where I can 'select' points in a figure. The selection will have to work similar to a 'brush', where all points are triggered in proximity of the mouse. The behaviour looks similar to the defualt brush function, but that function only allows dragging of a box. The data I use in my figures is more curved and complex, and would not suit the 'square' approach of the brush function very well.
I want the figure to work with the "enableDefaultInteractivity" behaviour of MATLAB UIAxes. This means that i can drag the figure by clicking and holding the mouse, and zoom with the mousewheel on the location the pointer is at that point. When clicking a button, I want to switch to a "brushing-mode", where i can click in the figure and start "painting" datapoints in my figure.
The Problem:
Whenever the WindowButtonDownFcn of the app itself is added, this will automatically disable the enableDefaultInteractivity of the figure. By default, I would right-click the "app.UIFigure" in the Component Browser, and select "Callbacks -> Window Callbacks -> add WindowButtonDownFcn callback", but this immediately disables the enableDefaultInteractivity and I cannot restore it.
As a workaround, I defined the desired WindowButtonDownFcn in the apps startupFcn as follows:
app.UIFigure.WindowButtonDownFcn = {@MouseDown, app};
This at least means I have expected behaviour up to the point of performing the desired tasks. However, when the datapoint selection is completed (through a WindowButtonMotionFcn and a WindowButtonUpFcn), the enableDefaultInteractivity is disabled, and I cannot restore it.
The Code:
I have appended a dumbed-down app that demonstrates the problem. It is a very simple app containing one single figure and one button. Upon running the code, a square is plotted. The figure can be dragged and zoomed as expected. When the button is pressed, the user can click (and hold down!) the mousebutton in the figure, and drag the displayed 'brush' over the datapoints, which will then light up.
When releasing the button, the points remain visible. However, now the figure cannot be dragged or zoomed anymore.
Any help is appreciated! Kind regards,
Mark

Respuesta aceptada

Benjamin Kraus
Benjamin Kraus el 8 de Jul. de 2022
There seems to be a subtle bug going on with your app. I can narrow down the issue to this code:
% Code in your startupFcn
f = figure;
ax = axes;
enableDefaultInteractivity(ax);
f.WindowButtonDownFcn = @(~,~) disp('');
% At this point in the script, the act of setting WindowButtonDownFcn
% *should* have disabled the default interactivity, but due to a bug it
% remains active.
% Code in ButtonPushed
disableDefaultInteractivity(ax)
enableDefaultInteractivity(ax);
% At this point in the script, enableDefaultInteractivity didn't work
% because WindowButtonDownFcn is not empty, so interactions remain
% disabled.
Fortunately, there is a really easy fix to this issue: Move most of the code in your startupFcn into ButtonPushed.
Specifically:
  1. Don't set WindowButtonDownFcn or WindowButtonMotionFcn or WindowButtonUpFcn within startupFcn.
  2. Instead, set all three Fcn properties within your ButtonPushed callback (before calling uiwait), and then clear all three property values after uiwait returns.
  3 comentarios
Benjamin Kraus
Benjamin Kraus el 8 de Jul. de 2022
Question 1: "Is this good practice? Or is there a better approach?"
Creating separate M-files is fine, but another (better) approach is to add methods/functions to your App. Go do the "Code View" tab, and then click "Functions" in the "Code Browser" panel, then click the green plus button. You can decide whether the functions should be private or public depending on your needs. This will allow you to add functions that live on your App and will have access to the properties of your app (if you want).
This doc page has more details: Reuse Code Using Helper Functions
Question 2: "Is this normal behaviour? Or is there a command to force this withouth moving the cursor?"
I'll be honest, I'm not sure if that is expected or not. Can you confirm that the call to enableDefaultInteractivity is running immediately when you release the mouse button? Or is enableDefaultInteractivity only running once the mouse has left the axes?
If enableDefaultInteractivity is running immediately when the mouse button is released, then I'm not sure what to say. I'll have to ask one of my colleagues about this question.
Mark Kamps
Mark Kamps el 11 de Jul. de 2022
Q1:
I got my function definition wrong, apparently I have to call them as @app.MouseUp, rather than @MouseUp. Now it works as expected.
Q2:
I can confirm that the enableDefaultInteractivity is defined immediately when the mouse button is released. I tried it on a multitude of locations and/or with duplicates of the enableDefaultInteractivity command.
I found that defining "axes(app.Figure)" will immediately enable the enableDefaultInteractivity, although this does leave a noticable 'flicker' on my axes. I am not sure if this is how it shoudl work?
In any way, thank you for the assistance!

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Develop Apps Using App Designer en Help Center y File Exchange.

Productos


Versión

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by