How do I check if a slider in a MATLAB GUI have been used, i.e. the user have interacted with the slider?
The slider is given by the following GUI code:
uicontrol(fig,'Style','Slider','Units','characters','Position',[17.1+f*iwidth 10.5 8 59.6],'Min',0,'Max',1000,'Value',500,'SliderStep', [1/500 , 20/500 ],'Tag',['slider' int2str(f)]);
Is there a clever way of doing this?
The only thing you need to add is a callback function. You can add it with the same uicontrol command.
uicontrol(fig,'Style','Slider','Units','characters','Position',[17.1+f*iwidth 10.5 8 59.6],'Min',0,'Max',1000,'Value',500,'SliderStep', [1/500 , 20/500 ],'Tag',['slider' int2str(f)], 'Callback', #myfunc);
then you need to write the myfunc, something like this:
function myfunc(source,event)
value = source.Value % This is the position of the slider
end
Related
I am running the drawnow statement from a callback function within a MATLAB GUI to update the state of a button. At the beginning of the callback (which has high runtime) I alter the properties of the button and force an update with drawnow. While updateing properly, the button remains rendered 'pushed down' instead of 'disabled'. After the callback is finished, the button is updated again and now rendered 'disabled'.
Take following minmal (not) working example:
function simple_example()
h = figure();
% add a button, give it some properties and a callback
uicontrol(h,...
'Style','pushbutton',...
'String','I am enabled',...
'Units','normalized',...
'Position',[0.5 0.5 0.4 0.4],...
'Callback',#btn_callback);
end
function btn_callback(hObject, ~)
set(hObject,'Enable','off');
set(hObject,'String','I am disabled');
drawnow;
pause(3);
end
Is there a way to change this behavior and have the button appear disabled while the callback is still executing?
As you are asking about appearance here's a workaround using uibuttongroup:
function simple_example()
h = figure();
b = uibuttongroup('Position',[0.5 0.5 0.4 0.4]);
bgcolor = b.BackgroundColor;
% add a button, give it some properties and a callback
uicontrol(b,...
'Style','pushbutton',...
'String','I am enabled',...
'Units','normalized',...
'Position',[-0.05 -0.05 1.1 1.1],...
'Callback',#btn_callback);
end
function btn_callback(hObject, ~)
set(hObject,'Enable','off');
set(hObject,'String','I am disabled');
drawnow;
pause(3);
end
Here, you fit the button within a uibuttongroup, which normally groups several uibuttons and then set the button size bigger than the actual uibuttongroup, so the borders don't appear.
However, this let's you lose the button down rendering. You could get that back by altering the uicontrolgroup's border properties.
Update:
This seems to be OS-specific. On OS X your code works just fine, as far as I can see. Windows, I don't know, but according to your comment neither my version, nor yours seems to fix the issue. On Ubuntu, on the other hand, my answer solves the problem.
Quite simply, I'm trying to create a borderless button in a MATLAB GUI. The reasons are mostly aesthetics, so no need for a debate on why it should be borderless.
I already know that this cannot be done using the built-in MATLAB uicontrol alone, since the border of the button is not an accessible property in MATLAB. Thus, the underlying JAVA code (upon which MATLAB is written), must be accessed in order to manipulate the border. This is where I get lost, since I've only ever programmed in MATLAB.
I followed an example from here:
http://undocumentedmatlab.com/blog/borderless-button-used-for-plot-properties
But I'm still not getting a borderless button.
Here is a simple code example (NOTE the use of Yair Altman's findjobj which is available on the MATLAB file exchange):
f=figure('Menubar','none', 'Position',[200 200 300 200]);
p=uipanel(f, 'BackgroundColor', [0 0 1]);
h = uicontrol('parent', p, ...
'Style','pushbutton', ...
'String','click', ...
'TooltipString', 'you should click this' ...
'Units','normalized', ...
'Position',[0.3 0.3 0.5 0.5], ...
'BackgroundColor', [0 0 1]);
jh = findjobj(h);
jh.setBorder(javax.swing.BorderFactory.createEmptyBorder());
%attempt 1 does not remove border
jh.border=[];
%attempt 2 does not remove border
jh.setBorder([]);
%attempt 3 does not remove border
jh.border=javax.swing.BorderFactory.createEmptyBorder();
%attempt 4 does not remove border
Any thoughts on where I've gone wrong? Thanks!
You shoud add two lines:
jh.setBorderPainted(false);
jh.setContentAreaFilled(false);
It is not clear to me what you mean with "borderless".
Looking at the example on the Web page you posted, I assume you are looking for something like an "invisible" pushbutton.
If so, you might consider this alternative way:
insted of having a pushbutton you might have a static text uicontrol
make its backgroundcolor the same of the GUI backgroundcolor (it will become "invisible" and without any border)
do not set any string in the static text uicontrol
set the enable property of the static text uicontrol to off
define, for the static text uicontrol the ButtonDownFcn
write the code you want to execute by pushing the pushbutton in the ButtonDownFcn
When you press the mouse button on the "invisible" static text uicontrol, its ButtonDownFcn will be executed.
You just have to remember ... were the "invisible" static text uicontrol is.
Hope this helps.
The border is affected by the fly-over appearance feature. http://undocumentedmatlab.com/blog/undocumented-button-highlighting
You need to add
jh.setFlyOverAppearance(true);
Worked for me.
I have a GUI with a uitable that the user can edit values in. I have a CellEditCallback function for that table that triggers and checks for input errors in the cells whenever a user presses enter while editing a cell or clicks outside the cell. That works great, but I also have a pushbutton that uses data from that table and my current problem is that when the pushbutton is clicked before any other spot outside the cell is clicked, or before enter is pressed for that matter, the pushbutton callback runs first, and after that callback finishes then the CellEditCallback runs. This is not ideal, as I need to check for errors before I use the data in my calculations. So, does anybody have any ideas on how to have the CellEditCallback function run first?
This code produces the problem I'm having:
% If you edit a cell and immediately click the button before clicking
% outside the cell or before hitting enter, the button's callback triggers
% before the CellEditCallback
function temp
% Create Figure
mainFig = figure('Units','characters',...
'Position',[45 5 200 50],...
'Renderer','opengl');
% Create uitable
tempData(1:10,1:5) = {''};
mainTable = uitable('parent',mainFig,...
'Units','characters',...
'Position',[5 25 180 20],...
'ColumnEditable',[true],...
'ColumnFormat',{'char'},...
'ColumnWidth',{150 150 150 150 150},...
'Data',tempData,...
'CellEditCallback',#enterDataCallback);
% Create Button
mainButton = uicontrol('Parent',mainFig,...
'Units','characters',...
'Position',[5 10 180 10],...
'Style','pushbutton',...
'String','Button',...
'Callback',#buttonCallback);
% Function for when cell data is edited
function enterDataCallback(src,evt)
disp('Cell Edited')
end
% Function for when a button is pressed
function buttonCallback(src,evt)
disp('Button Pressed')
end
end
Note 1: I did try using uiwait and waitfor but the problem isn't that the CellEditCallback function gets interrupted, it just is triggered after the pushbutton callback.
Note 2: That was a very basic description of what the functions do, but I do need the callbacks to trigger in that order because other things like flags and important variables in an outer function are set in the CellEditCallback so I need to have that callback run before the pushbutton one.
Thanks!
I contacted MATLAB Support about this problem and they told me that the callbacks occurring in that order is indeed an error and that it is fixed in the 2014b prerelease. However, to work around the error, I managed to do some messy coding to call the CellEditCallback from inside the Push Button Callback and then set a flag to make sure the CellEditCallback doesn't fire after the Push Button Callback is done.
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 have a set of data that i have pulled out of the database. I have displayed them in a figure window, but i would like to have a button in which where it closes the figure window or does some other function to it.
This is the code that i have so far :
f = figure('Position',[200 200 250 500]); % size of the figure object
dat = listofPdb.Data;
set(f,'name','List of PDBs available','numbertitle','off') %renames the Title Figure
cnames = {'PDB-Codes'};
rnames = {};
t = uitable('Parent',f,'Data',dat,'ColumnName',cnames,...
'RowName',rnames,'Position',[100 100 95 350]);
Please advise.
You need to define CloseRequestFcn property of the figure:
set(f,'CloseRequestFcn', #closereq)
where closereq is a function what to do when figure is closed.
See Figure properties for more information and examples.
Update (after chat in comments):
For a pushbutton you can define the callback function just to close the figure (insert close(get(hObject,'Parent')) into pushbutton1_Callback) and the CloseRequestFcn will do the rest.
On the other hand, if you want the pushbutton to do something before closing the figure, but don't want to do it with standard closing, then just insert those actions to the pushbutton callback, not to CloseRequestFcn.
Type guide and design your figure. Than place a pushbutton over it, right click -> closing function. And define the behaviour you want to have for closing the figure.