I am trying to animate a clock hand's movement using MATLAB. I created 'draw_clock()' program/script in a file named 'draw_clock.m' that goes something like this.
function draw_clock()
set_figure();
draw_clock_hands();
end
function set_figure()
figure;
hold on;
axis off;
title('Clock');
end
Then I have a script file named 'animate_clock.m' that has something like this:
hours = 0:12;
minutes = 0:59;
for i = 1:numel(hours)
for j = 1:numel(minutes)
draw_clock();
pause(0.05);
refresh;
end
end
When I run 'animate_clock.m', new window/clock figure for every frame is opened instead of redrawing on the same canvas/figure. I understand why this is happening because 'set_figure()' is being called every time 'draw_clock()' is called. I'm new to MATLAB, so if there's a way to stop creating new figure with the code skeleton above. I guess if I can detect if there's a figure object already opened, then I can skip calling 'set_figure()' inside 'draw_clock()' next time it is being called?
Thank you in advance for your answers!
So after searching and reading the doc a bit, I think there are a couple of different ways to detect if a matlab figure already exists. One that I found useful (and relatively simple) is to:
- assign the 'Name' property to the figure window
- find if an object with the assigned name exists using 'findobj(...)' method
- if figure already exists, use 'hold on' to reuse the old figure
- else, create a new figure with the name 'figure('Name', 'foo figure')'
For my case, 'set_figure()' method will become something like this:
function set_figure()
fig_name = 'My Clock';
if isempty(findobj('Name', fig_name))
figure('Name', fig_name);
end
hold on;
axis off;
end
Hope someone can come and improve it to become more robust. :)
Related
As the title states, I need to get a handle for my Matlab application. My class is derived from matlab.apps.AppBase and is app.UIFigure (if that matter, I'm still learning Matlab). My main goal is to change the mouse cursor to watch after a button is clicked and data is processed in the background.
I have tried:
set(gcf,'Pointer','watch')
But gcf is just empty, so it creates a new figure. I have also gotten all of the figures, using:
figs = findall(groot,'Type','Figure')
Which finds all of the figures I am using. I believe that I need to get the overall application figure and find the handle, but I am unsure how to do that.
There is no pointer property for uifigure; otherwise, you would be able to use app.UIFigure.Pointer = 'watch' as suggested by #CrisLuengo.
However, specially for uifigure MATLAB provides a nice looking and powerful progress bar uiprogressdlg. You can make it indeterminate with uiprogressdlg.Indeterminate = on;. I find this working pleasingly well.
Here is an example:
f=uifigure;
progressdlg=uiprogressdlg(f,'Title','Progress','Message', 'Doing something please wait', 'Indeterminate','on');
pause(10); % Run your algorithm.
% Delete the progress bar after work done.
progressdlg.delete();
I'm refactoring an existing (working) MATLAB code, in particular I'm extracting a new class from a piece of structured code that creates a figure, and when I do that, I get an error caused by axes of the figure getting deleted (my variable now says it contains a handle to deleted axes).
In more detail, the current version of the code does something like this:
Overlay = figure
overlayAxes = subplot(1, 2, 1, 'Parent', Overlay)
... (other stuff)
imshow(... other parameters ..., overlayAxes)
(I'm mentioning "other stuff" and "other parameters" to clarify the imshow line is not directly above the overlayAxes assignment, just in case you think I should look for anything in particular before the call to imshow)
This works fine. My refactor is consists in moving the creation of Overlay to a class (in other words, make it more "OOP-like"). As a first step, I moved it to a class like this:
classdef MyGUI < handle
properties(SetAccess = public)
Overlay
overlayAxes
end
methods
function obj = MyGUI()
obj.Overlay = figure;
obj.overlayAxes = subplot(1, 2, 1, 'Parent', obj.Overlay);
end
end
end
And then I referenced this new class where Overlay was originally created like this:
GUI = MyGUI;
Overlay = GUI.Overlay;
overlayAxes = GUI.overlayAxes;
(I made those two variable assignments so I didn't have to change the rest of the code right now - because it references Overlay not GUI.Overlay - in particular the call to imshow)
So, when I do this, the call to imshow fails saying:
Error using imshow>validateParent (line 375)
HAX must be a valid axes handle.
As it turns out, when I debug and inspect overlayAxes, it says it contains a handle to deleted axes.
I've read some articles explaining that axes get deleted when new figures are created and such, but the only change I'm making is converting the figure creation from a local variable to a class property, so I don't feel like is something related to side-effects of calling plot functions again or anything like that, but maybe something about passing by reference, object lifecycle, or something that I'm missing completely, not really sure.
Why are my axes getting deleted? Thanks!
I have a question that I can seem to wrap my head around,
I have created a gui that uses the unput from the user to run a script within the gui and later display the results to the user interface. What I dont understand is that everything is running ok until I choose one particular file. The interesting and mind boggling is that the script jumps a nested loop (whie this dosent happen for the other choices). I dont understand why this happens and cant find anything relavent on the internet. The script stand alone executes perfectly.
for i=2:length(Data_last_values)
for j=2:length(temp_nov)
if Data_last_values(i,4)>temp_nov(j,1) & Data_last_values(i,4)<temp_nov(j-1,1)
Data_last_values(i,9)=Data_last_values(i,3)+Q_leak_dot(j);
disp('gone through loop')
end
end
end
displayed above is the part of the nested loop that matlab chooses to skip. would any one know why this happens? below I present the gui script:
if not(isempty(cell2mat(z)))
run Daughter
assignin('base','avg',data(:,8))
axes(handles.axes1);
markerSize = 50;
scatter(Data_last_values(:,4),Data_last_values(:,9),markerSize,Data_last_values(:,5)) % -> volumetric mass flow is used in the color bar
colormap(jet(20));
h=colorbar;
xlabel('T_{water}[C]')
ylabel('Q_{out} [W]')
ylabel(h, 'Volumetric Flow [Lt/min]')
grid minor
myvar = evalin('base', 'avg');
y=line([0 max(Data_last_values(:,4))], [mean(myvar) mean(myvar)]);
xlim([0 max(Data_last_values(:,4))])
I'm writing a matlab program and I'm trying to pass around my handles struct to ALL my callbacks. The only problem is that I'm using GUIDE and I can't pass in handles as an argument to a function I created:
%The proper slider callback: Deleted the default within GUIDE
function sliderContValCallback(hFigure,eventdata)
%test it out- get the handles object and dispay the current value
%getappdata(handles.video_loader_button,'handles');
handles = guidata(hFigure);
handles.currentFrame = floor(get(handles.slider,'Value'));
set(handles.frameBox,'String',num2str(handles.currentFrame));
fprintf('slider value: %f\n',get(handles.slider,'Value'));
updateAxes(handles);
The problem is that the way I'm 'getting' handles right now is that it isn't really the same handles that the rest of the UI object callback functions are using. I also thought of passing handles around with getappdata, but you need handles to even do that so I'm stuck. This has been causing some problems, any help as to how to get around this would be awesome, thanks!
EDIT:
I deleted the call back generated by GUIDE, so that I could use sliderContValCallback as a function handle and call it here:
handles.sliderListener = addlistener(handles.slider,'ContinuousValueChange',...
#(hFigure,eventdata) sliderContValCallback(hObject,eventdata));
for continuous updates as the user drags the slider(This is used to scroll through a video, and its working well).
The real reason I'm questioning this is because when I call:
allCoords = getappdata(handles.axes1,'mydata');
coordsXYZ = allCoords.clickcoordinates; %Do this to access the field 'allCoords' within 'mydata'
curIndex = allCoords.currentIndex;
if numel(coordsXYZ)>0
for i = 1:length(coordsXYZ)
coordXY = [coordsXYZ(i).x,coordsXYZ(i).y];
%viscircles(handles.axes1,coordXY,1,'EdgeColor','r');
hold on;
plot(coordsXYZ(i).x,coordsXYZ(i).y,'o');
end
end
everything works but a figure is generated for some reason, the plot is drawn to an image on handles.axes1. It's weird because this random figure pops up ONLY when I update the slider by moving it.
Stupid, simple question - is the value of gcf in matlab always going to be the figure number of the active figure? I.e., if I'm working on Figure 5, will gcf always return 5?
GCF returns the handle of the "current figure". This is always the figure number of the active figure. However, if you click on a different figure in the meantime, that other figure will become active. Thus, if you already know what figure you're working with, because you either forced the handle to 5 by calling figure(5), or because you captured the handle in a variable by calling fh=figure; it is safer that you use the handle instead of gcf whenever you want to modify the figure to avoid risking to inadvertently making another figure active.
Also, if there is no figure currently open, gcf will open a new figure.
This is a little more complicated than a simple "yes" or "no" answer. The handle for the current figure will generally match the number displayed at the top left of the figure window, but this number is only displayed when the 'NumberTitle' figure property is set to 'on' (the default).
Another wrinkle is that the figure handle is not guaranteed to be an integer. There is an 'IntegerHandle' figure property which determines if the handle created for the figure is an integer or a non-reusable real number. If this property is set to 'off', you get handle values that aren't integers, so the first figure that you open won't have a handle of 1. For example:
>> hFigure = figure('IntegerHandle','off') %# The only window open
hFigure =
173.0040
And the figure is numbered accordingly:
Notice that when the figure number and handle are displayed, there is some round-off of the number. The figure window only displays 6 digits past the decimal place. It becomes apparent that you're dealing with floating point numbers when you change the format of the Command Window to show more decimal places:
>> format long
>> hFigure
hFigure =
1.730040283203125e+002
In this case, the displayed figure number and the figure handle differ slightly.
Yes, gcf will return the handle of the currently selected (or active) figure. From the documentation,
H = GCF returns the handle of the current figure. The current
figure is the window into which graphics commands like PLOT,
TITLE, SURF, etc. will draw.
But also remember that:
The current figure is not necessarily the frontmost figure on
the screen.
One way to make a figure "current" is:
Clicking on uimenus and uicontrols contained within a figure,
or clicking on the drawing area of a figure cause that
figure to become current.
Another way is to use the figure handle. i.e., if you called the figure as h=figure;, then figure(h) will make it the current figure.