Geoaxes zoom not working after adding ButtonDownFcn.

I have an app built in AppDesigner with a map plotted in geoaxes. I need to zoom in and out but I also need to do some action when I click on the map. The problem is that:
  • zoom works perfectly when no buttondownfcn is added
f = uifigure;
gx = geoaxes();
geoscatter(gx,10,10)
  • zoom does not work at all when buttondownfcn is added.
f = uifigure;
gx = geoaxes(f);
geoscatter(gx,10,10)
gx.ButtonDownFcn = 'disp(''hello'')';
I need to use both functionalities. What should I do?

 Accepted Answer

Assigning the button down function disables pan/zoom interactions. Until R2023a, it could be fixed by resetting the default interactivity of the axes.
gx = geoaxes;
geoscatter(gx,10,10)
enableDefaultInteractivity(gx) % * <-- must be before assigning ButtonDownFcn
gx.ButtonDownFcn = 'disp(''hello'')';
* See Jan Studnicka's comment below.
Update
This solution works beyond R2023a. It creates an event listener on the figure that responds any time a mouse button is pressed within the the figure. The listener callback checks whether the mouse button press was within the geoaxes before executing a simple display action.
fig = figure();
gax = geoaxes(fig);
geoscatter(gax,10,10)
event.listener(fig, 'WindowMousePress', @(src,evt)ButtonDownResponseFcn(src,evt,gax));
function ButtonDownResponseFcn(~,evt,gax)
% gax is the geoaxes handle. Check whether the hit object was the geoaxes.
if isequal(evt.HitObject, gax)
disp('Geoaxes hit!')
end
end

11 Comments

Thank you Adam. Your code works and answers my question. However it does not work for UIFIGURE which is actually what I need as the app is built in AppDesigner. Try this code:
f = uifigure;
gx = geoaxes(f);
geoscatter(gx,10,10)
gx.ButtonDownFcn = 'disp(''hello'')';
enableDefaultInteractivity(gx)
Does not even work when the geoaxes ButtonDownFcn is substituted by uifigure WindowButtonDownFcn!!!
This has got to be a bug - in both regular figures and uifigures. It just so happens that enableDefaultInteractivity patches the bug with regular figures. None of this is mentioned in the documentation.
Even without the ButtonDownFcn, if I zoom in and out quickly in R2021a I iteratively get this warning,
Warning: A value of class "double" was indexed with no subscripts specified. Currently the result of this operation is the indexed value itself, but in a
future release, it will be an error.
> In matlab.internal.asynchttpsave/AsyncHTTPContentFileWriter/handleThreadIsFinishedEvent
In matlab.internal.asynchttpsave.AsyncHTTPContentFileWriter
In asyncio/Channel/onPropertyChanged (line 471)
In asyncio.Channel>@(source,data)obj.onPropertyChanged(data.Name,data.Value) (line 401)
You should report this as a bug and feel free to point to this thread. Let us know what they say.
Fortunately the zoom buttons on the axes toobar still function.
I have just found out, that enableDefaultInteractivity works for uifigure too, however you need to call it before you add ButtonDownFcn callback:
f = uifigure;
gx = geoaxes(f);
geoscatter(gx,10,10)
enableDefaultInteractivity(gx)
gx.ButtonDownFcn = 'disp(''hello'')';
Thanks for the update!
Has someone already reported this bug? It appears to still be there and it is causing a lot of trouble for me.
> Has someone already reported this bug?
Yes.
Does the workaround in my answer now work for you?
None of the approaches work for me unfortunately :(
X = randn(100,4);
hax = gobjects(4,1);
figure
ht = tiledlayout();
for k = 1:4
hax(k) = nexttile();
s = scatter(1:100,X(:,k));
enableDefaultInteractivity(hax(k))
% uncomment one of the two lines to trigger issue
% s.ButtonDownFcn = @onButtonDown
% hax(k).ButtonDownFcn = @onButtonDown
end
function onButtonDown(obj, ~, evnt)
disp("jojo")
end
Is there any other option to fire an event, when a datapoint is selected and deselected? I have to sync datapoints across multiple axes and I have no other idea but to use the datacursor :/
@Jan Kappen, check out my updated answer for another workaround. I tested it in R2023a and R2025a.
Dear @Adam Danz beautiful, so the key point is no to use the ButtonDownFcn, or WindowMousePress, which appararently kills all default axis interactions (so why in hell are the callback properties empty then?), but to add an additional listener to the fired event.
Awesome, thanks!
Edit: all those events seem to be hidden and thus not really wanted to be accessed?
events("matlab.ui.Figure")
Events for class matlab.ui.Figure: ObjectBeingDestroyed PropertyAdded PropertyRemoved
There are way more including the one you mentioned.
m = ?matlab.ui.Figure; string({m.EventList.Name})'
ans = 29x1 string array
"Close" "KeyPress" "Help" "KeyRelease" "WindowMousePress" "WindowMouseRelease" "WindowMouseMotion" "WindowScrollWheel" "WindowKeyPress" "WindowKeyRelease" "WindowStateChanged" "FigureActivated" "FigureDeactivated" "ViewReady" "ChildAdded" "ChildRemoved" "ButtonDown" "BindablePropertyChanged" "Reset" "ObjectBeingDestroyed" "PropertyAdded" "PropertyRemoved" "NodeChildAdded" "NodeChildRemoved" "LocationChanged" "SizeChanged" "ScrollableViewportLocationChanging" "ScrollableViewportLocationChanged" "ThemeChanged"
Can we get an update on how to get access to the other events? I cannot use the event you listed in your answer @Adam Danz
In addition, is there any plan to get this behaviour fixed so that we can re-establish control of the interactivity options?

Sign in to comment.

More Answers (1)

"Sometimes MATLAB® automatically disables the built-in interactions. For example, they might be disabled for charts that have special features, or when you implement certain callbacks such as a WindowScrollWheelFcn."
However, with geoaxes you can easily implement zooming in / out by using WindowScrollWheelFcn callback of the uifigure. This is an example created from the documentation's example on "how to use WindowScrollWheelFcn":
function scroll_wheel
% Shows how to use WindowScrollWheelFcn in combination with geoaxes and
% ButtonDownFcn callback.
f = uifigure('WindowScrollWheelFcn',@figScroll,'Name','Scroll Wheel Demo');
gx = geoaxes(f);
geoscatter(gx,10,10)
gx.ButtonDownFcn = 'disp(''hello'')';
title(gx,'Rotate the scroll wheel')
function figScroll(~,event)
if event.VerticalScrollCount > 0
gx.ZoomLevel = gx.ZoomLevel-0.1;
elseif event.VerticalScrollCount < 0
gx.ZoomLevel = gx.ZoomLevel+0.1;
end
end
end

1 Comment

+1 Good idea, Jan. Note that this zooms into the center of the axes rather than zooming into the location of the cursor within the axes.
It's still not clear to me why a ButtonDownFcn would prevent zoom interaction since that callback function does not respond to the scroll wheel. I also find it odd that adding the ButtonDownFcn disables zoom interaction but calling enableDefaultInteractivity can turn it back on in regular figures - that sounds buggy to me. Lastly, I wonder why applying enableDefaultInteractivity doesn't fix the problem with uifigures.
BTW, I also get the same interative warning when zooming in/out using this method (r2021a)
Warning: A value of class "double" was indexed with no subscripts specified. Currently the result of this operation is the indexed value itself, but in a
future release, it will be an error.
> In matlab.internal.asynchttpsave/AsyncHTTPContentFileWriter/handleThreadIsFinishedEvent
In matlab.internal.asynchttpsave.AsyncHTTPContentFileWriter
In asyncio/Channel/onPropertyChanged (line 471)
In asyncio.Channel>@(source,data)obj.onPropertyChanged(data.Name,data.Value) (line 401)
There's clearly some cleaning up to do by MW.

Sign in to comment.

Categories

Products

Release

R2021a

Asked:

on 19 May 2021

Edited:

on 28 Oct 2025

Community Treasure Hunt

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

Start Hunting!