I am trying to set the background color of my gui button to a different color while the program is busy doing the computation. If I just set the color to change when the button is clicked it changes; However if I add another line of code AFTER the actual computation to change the color back to it default, the color never gets changed the first time.
function FitData_button_Callback(hObject, ~, handles) %#ok<DEFNU>
set(handles.FitData_button,'BackgroundColor',[0 204 0]./255,'String','Fitting Data');
% do some computation that takes time here...
% this line causes the first instance of 'set' not to work
set(handles.FitData_button,'BackgroundColor',[237 237 237]./255,'String','Fit Data');
If I change the properties for the second time I call 'set', it does change from the default to what was specified the second time (and it does this after the long computation is finished). However, the first set of properties never get assigned.
So it seems like I am only allowed to set the BackgroundColor and String properties one time, which does not make any sence.
What gives?
thanks
The short answer is to put a "drawnow" in the middle of your computations. The long answer is best illustrated by Yair Altman on his blog (which is FANTASTIC by the way) - http://undocumentedmatlab.com/blog/matlab-and-the-event-dispatch-thread-edt/
Related
I know that one can insert a colorbar by clicking the colorbar icon in the clustergram GUI. Is there a way to do it programmatically?
I tried
cgo = clustergram(data)
colorbar;
This makes a colorbar in a new figure window. How can a colorbar be created with proper positioning in a clustergram figure as if the button was clicked?
There is a function buried away (HeatMap.plot>showColorbar) that neatly positions the colorbar to the left of both the heat map and the dendogram (the lines). Just running colorbar(...) will mess up the relative positioning of the dendogram and the heatmap. So you need to somehow run the callback or carefully duplicate all of the position computations. It's easier to just run the callback. Here's how.
To create the colorbar programmatically for a clustergram, and keep the color bar button in sync, you need to use the button's assigned callback and set the button's state.
Create the clustergram:
load filteredyeastdata
cgo = clustergram(yeastvalues(1:30,:),'Standardize','Row');
Get the handle for color bar button:
cbButton = findall(gcf,'tag','HMInsertColorbar');
Get callback (ClickedCallback) for the button:
ccb = get(cbButton,'ClickedCallback')
ccb =
#insertColorbarCB
[1x1 clustergram]
That gives us a handle to the function assigned by the callback (#insertColorbarCB), and the function's third input argument (the clustergram object). The button's handle and an empty event object are implicitly the first two arguments.
Change the button state to 'on' (clicked down):
set(cbButton,'State','on')
Run the callback to create the colorbar:
ccb{1}(cbButton,[],ccb{2})
Note that the button State must be changed to 'on' first, otherwise the callback won't do anything.
I just managed to solve this problem.
What I did:
I added this function to the clustergram code (I put it at line 1486)
%%%%%%%%%%%%%%
function insertColorbarCBALWAYS(obj)
hFig= gcbf;
obj.Colorbar = true;
end
%%%%%%%%%%%%%%%
and then at line 415 of the clustergram.m file I added this line of code
insertColorbarCBALWAYS(obj);
to call the above function. Save and go: now the colorbar will always be there, once the clustergram is drawn.
Previous method was not working for me so I made this workaround.
One may even save the new clustergram code as clustergramCM such that you can draw cgram in both ways.
I am trying to implement a very simple GUI that consists of just one pushButton. I want it to begin by just having START as a label. Then on press it changes to STOP. When the user clicks the button the first time the callback sets a boolean to true and changes the label. When the Button is clicked a second time the boolean is changed to false and the GUI closes.
I can't find anything on how to make a simple GUI like this in MATLAB. the GUIDE tool makes no sense to me and seems to generate so much useless code. Matlab buttons are wrappers for jButtons as seen here
GUIDE is quite straightforward - the automated tool generates stubs for all the callbacks, so that all is left is to fill in the code to be executed whenever the callback runs. If you prefer to create the GUI programmatically, you can create the button you want as follows:
%# create GUI figure - could set plenty of options here, of course
guiFig = figure;
%# create callback that stores the state in UserData, and picks from
%# one of two choices
choices = {'start','stop'};
cbFunc = #(hObject,eventdata)set(hObject,'UserData',~get(hObject,'UserData'),...
'string',choices{1+get(hObject,'UserData')});
%# create the button
uicontrol('parent',guiFig,'style','pushbutton',...
'string','start','callback',cbFunc,'UserData',true,...
'units','normalized','position',[0.4 0.4 0.2 0.2])
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.
In Matlab, I would like to update the data plotted in a set of axes when the user zooms into the plot window. For example, suppose I want to plot a particular function that is defined analytically. I would like to update the plot window with additional data when the user zooms into the traces, so that they can examine the function with arbitrary resolution.
Does Matlab provide hooks to update the data when the view changes? (Or simply when it is redrawn?)
While I have yet to find one generic "redraw" callback to solve this question, I have managed to cobble together a group of four callbacks* that seem to achieve this goal in (almost?) all situations. For a given axes object ax = gca(),
1. Setup the zoom callback function as directed by #Jonas:
set(zoom(ax),'ActionPostCallback',#(x,y) myCallbackFcn(ax));
2. Setup a pan callback function:
set(pan(ax),'ActionPostCallback',#(x,y) myCallbackFcn(ax));
3. Setup a figure resize callback function:
set(getParentFigure(ax),'ResizeFcn',#(x,y) myCallbackFcn(ax));
4. Edit: this one no longer works in R2014b, but is only needed if you add, e.g., a colorbar to the figure (which changes the axis position without changing the figure size or axis zoom/pan). I've not looked for a replacement. Finally, setup an undocumented property listener for the axes position property itself. There is one important trick here: We must hold onto the handle to the handle.listener object as once it's deleted (or leaves scope), it removes the callback. The UserData property of the axes object itself is a nice place to stash it in many cases.
hax = handle(ax);
hprop = findprop(hax,'Position');
h = handle.listener(hax,hprop,'PropertyPostSet',#(x,y) myCallbackFcn(ax));
set(ax,'UserData',h);
In all these cases I've chosen to discard the default callback event arguments and instead capture the axis in question within an anonymous function. I've found this to be much more useful than trying to cope with all the different forms of arguments that propagate through these disparate callback scenarios.
*Also, with so many different callback sources flying around, I find it invaluable to have a recursion check at the beginning of myCallbackFcn to ensure that I don't end up in an infinite loop.
Yes, it does. The ZOOM mode object has the following callbacks:
ButtonDownFilter
ActionPreCallback
ActionPostCallback
The latter two are executed either just before or just after the zoom function. You could set your update function in ActionPostCallback, where you'd update the plot according to the new axes limits (the handle to the axes is passed as the second input argument to the callback).
I'm working on a gui using GUIDE in MATLAB, and from what I've read it looks like MATLAB updates the UI controls based on a timer every so often. Is there a way to force it to update the UI controls, so I can make it update in the middle of the function? Right now I have a function that does, simplifed, something like
set(handles.lblStatus,'String','Processing...')
%function that takes a long time
set(handles.lblStatus,'String','Done')
Since MATLAB doesn't update the GUI during a Callback function, the user only ever sees 'Done' after a long period of waiting and never sees 'Processing'. I tried adding guidata(hObject, handles) after the first set, hoping it would force the screen to update, but it doesn't.
Try calling DRAWNOW.
set(handles.lblStatus,'String','Processing...')
drawnow
%function that takes a long time
set(handles.lblStatus,'String','Done')
I believe there is a drawnow function in matlab.
drawnow completes pending drawing events