I am building a GUI in Matlab that plots different functions in different plots according to the selected RadioButton. It looks like:
I want to select at which axes should the function be plotted. Therefore I need to know which of the RadioButton is selected. Then:
% Set default RadioButton
set(h.r1,'Value',1);
set(h.r2,'Value',0);
set(h.r1,'Callback',{#myRadioButton, h.r2}); % Set the other RadioButton to false
set(h.r2,'Callback',{#myRadioButton, h.r1}); % Set the other RadioButton to false
Then I call press one of any Button and call my plotting function which (should) evaluate(s) which axes it has to use:
set(h.b1,'Callback',{#myPlotFunction,...
get(h.r1,'value')*h.axes1+get(h.r2,'value')*h.axes2, h.x});
The problem is that I always get h.axes1 as input, no matter which RadioButton I choose.
Is this due to the definition of default values for RadioButton?
EDIT
Another edit: Ok, now we're dynamically assigning the button handles and xdata inside of the radiobutton callback.
Due to some peculiarities with MATLABs handling of function handle arguments (see comments), my first answer doesn't work. This one does.
set(h.r1,'Callback',{#TurnOffRadio, h.r2, h.axes1, h.x});
set(h.r2,'Callback',{#TurnOffRadio, h.r1, h.axes2, h.x});
function TurnOffRadio(hObject, eventdata, radiohandle, axeshandle, xdata)
set(radiohandle, 'Value', 0);
set(h.b1,'Callback',{#myPlotFunction, axeshandle, xdata});
%// Repeat set statement for each button.
end %// You may nee to remove this end, depending on your conventions.
function myPlotFunction(hObject, eventdata, axeshandle, xdata)
%// do whatever here with axeshandle and xdata.
end %// You may nee to remove this end, depending on your conventions.
I've set up a toy example and run this exact code, and it produces the desired effect.
Let me know if this still doesn't solve the problem, and I'll keep digging.
Original
You're close. The problem is that when you set a callback function using a function handle and arguments, the arguments always remain what they were at the time that the callback was set. Essentially, they are passed only once, not dynamically each time the callback is executed. To work around this, just set the callback to turn off the other radio button directly using set.
set(h.r1,'Callback',{#set, h.r2, 'Value', 0});
set(h.r2,'Callback',{#set, h.r1, 'Value', 0});
Let me know if that doesn't work for you. Good luck!
Related
can I manually set WindowButtonDownFcn and selectively overwrite the right or middle-click, while preserving default behavior? Ultimate goal would be to copy figure to clipboard on some click.
set(gcf,'WindowButtonDownFcn',#(src,~) disp(src.SelectionType)); %this seemingly always overwrites default behavior of figure click
I tried this with following error msgs (scroll right)
listener(gcf,'WindowButtonDownFcn',#(src,~) disp(src.SelectionType)) %Event 'WindowButtonDownFcn' is not defined for class 'matlab.ui.Figure'.
listener(get(gcf,'parent'),'WindowButtonDownFcn',#(src,~) disp(src.SelectionType)) %Event 'WindowButtonDownFcn' is not defined for class 'matlab.ui.Root'
handle(gcf).addlistener(handle(gcf),'WindowButtonDownFcn',#(src,~) disp(src.SelectionType)) %Unrecognized method, property, or field 'addlistener' for class 'matlab.ui.Figure'.
and several more permutation using handle and event.listener with no success
Tested in Matlab 2019a.
EDIT: here's a template function to use with modifiers based on matlabgui's kind answer
%copies figure to clipboard when [control]+[right-click] anywhere on figure window (and leaving default functionality intact)
figure; plot(randi(100,1,100)) %random figure
addlistener ( gcf, 'WindowMousePress', #(src,~) myFavFunc(src,[]))
function myFavFunc(src,~)
if strcmp(src.SelectionType,'alt') && numel(src.CurrentModifier)==1 && strcmp(src.CurrentModifier,'control')
print -clipboard -dmeta
disp('copied figure to clipboard')
end
end
I dont know why Matlab hide some of the events for figures, you can get a list here:
hFig = figure;
mc = metaclass(hFig);
disp ( {mc.EventList.Name}' ) ;
From that info you can then add a listener to the mouse press event:
hFig = figure;
addlistener ( hFig, 'WindowMousePress', #(src,~)disp('myCallback' ))
That will leave the standard figure callback alone, instead of the disp command get it to run a function where you look at the figure property SelectionType to determine which mouse button was pressed. You could extend it to use the CurrentModifier property to determine if Ctrl, Shift or Alt was pressed to further customise it.
I have the following script:
im = imagesc(anImage, 'parent', gca);
set(im,'HitTest','off');
set(gca,'buttondownfcn', #someFunction)
My problem is that I want someFunction to return some values, but I am not sure how to do it in THIS particular scenario. It seems like the inline-ness is not letting me do this...
Thanks.
To make someFunction() set a value in your base workspace (I assume that is what you want to achieve), you can use the assignin() function.
An example for someFunction() that sets the variable axes_position to the the current axes' position is the following
function someFunction(hObject, event)
assignin('base', 'axes_position', get(hObject, 'Position'));
Have a look at the axis and figure properties pages in the MATLAB user guide on how to deal with user UI input in axes and figure controls (not enough reputation to add two more links).
However, you mention that you want to manipulate it in the next line of the program. If I understand correctly, this is what the guidata function is meant for: "store or retrieve UI data".
I've written a Matlab program which counts different values when are particular button is pressed (so far just the numbers of "yes" and "no"). I'm trying to add a key listener so that when I press, for example, n on the keyboard the button is pressed, or the same actions are completed. I have tried the addListener and keyfunclistener functions but neither seems to be working.
Here is an example of the button:
no=uicontrol(h_fig,'callback',countnonerve,'position',[.65 .07 .1 .08],'string','No','style','pushbutton','Units','normalized');
Any suggestions? It would be very helpful I'm not familiar with MatLab
You could try using the KeyPressFcn property of the figure to record/capture individual key presses:
function keypress_Test
h = figure;
set(h,'KeyPressFcn',#keyPressCb);
function keyPressCb(src,evnt)
disp(['key pressed: ' evnt.Key]);
end
end
The above code can be pasted into a file and saved as keypress_Test.m. A figure is created and a callback assigned to the KeyPressFcn property.
It can be easily adapted for your GUI. Wherever you have access to the figure handles (probably the h_fig from above) just add set(h_fig,'KeyPressFcn',#keyPressCb); and paste the keyPressCb code into the same file.
If you are counting the number of times a certain key is pressed, then you will have to save this information somewhere..probably to the handles structure. Is that the case? If so, then you can easily access this from the callback
function keyPressCb(src,evnt)
disp(['key pressed: ' evnt.Key]);
% get the handles structure
handles = guidata(src);
if ~isempty(handles)
% do something here - increment count for evnt.Key
% save the updated count
guidata(src,handles);
end
end
Try it out and see what happens!
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 learn GUI programming in matlab and for that purpose i am trying to create a simple multiplication calculator. I have done some programms in matlab without GUI but i am having difficulty in understanding GUI programming in Matlab. I have created the GUI but i dont know how to do the programming for that.
This is my GUI i made
EDIT TEXT 1; string= 0
EDIT TEXT 1; tag= edit1
EDIT TEXT 2; string= 0
EDIT TEXT 2; tag= edit2
STATIC TEXT 1; string= X
STATIC TEXT 1; tag= text3
STATIC TEXT 2; string= 0 (for showing results)
STATIC TEXT 2; tag= result
PUSHBUTTON; String= Calculate
PUSHBUTTON; tag=push_calc
i saved the given GUI in the name of "add" and created add.m . Can you tell me how to do programming for given gui.
The basic idea of matlab gui programming is the following:
Set up the figures
Enter the message loop
Both steps are taken care of by using the matlab gui editor (guide). The important thing is that you give control of the program flow over to the message loop. In order to get things done, you can tell the message loop to call a function whenever something happens.
In the gui editor, right click your pushbutton and select "View Callbacks -> Callback". This will automatically create such a function in you .m file where you can specify what happens when you push the button.
For a better understanding take a look at the Callback property of the pushbutton. Guide will have entered something like add('push_calc_Callback',hObject,eventdata,guidata(hObject)) which calls the main function (add) as a wrapper for your new callback function. You could have done that by yourself in the property editor or programmatically in the startup code.
I guess you want the following to happen:
Get the string values of edit1 and edit2
Convert the strings to numeric values
Perform the calculation
Set the string value of text3 to the string representation of the result
You can access the properties of the gui elements by using the handles available to you as the third function argument and the get and set functions. The handles structure is created by guide and the elements are named the same as the tag you specified.
In matlab code, this could look like this:
% --- Executes on button press in push_calc.
function push_calc_Callback(hObject, eventdata, handles)
% hObject handle to push_calc (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
x_string = get( handles.edit1, 'String');
y_string = get( handles.edit2, 'String');
x_numeric = str2num( x_string );
y_numeric = str2num( y_string );
result_numeric = x_numeric * y_numeric;
result_string = num2str( result_numeric );
set( handles.result, 'String', result_string);
Edit: The question is what is handles.edit1 and so on.
Whenever you want to do something with a widget like a button or a textbox, you have to be able to tell matlab exactly what widget you mean. Guide does a few things behind the scenes. One of them is to call uicontrol, which creates the widget and returns a random but unique number. This is a bit like a bank account number in the way that it is a handle to a resource that can be used to manipulate it. When you create a new pushbutton in guide and assign the tag "clickme" in the property editor, guide creates the pushbutton and stores the handle in a structure handles.clickme. That gives you an easy way to get the handle of any widget that you created if you can still remember what tag you assigned it.
Let's take the first line of the function:
x_string = get( handles.edit1, 'String');
That calls the function get with some number you should not care about as long as it the same number that matlab associates with the edit1 widget and a property name from the property editor, in this case 'String'. That would be the same as you clicking through all the window elements until the property editor shows a tag of 'edit1', and for that object you find the value for the property named 'String'.
The properties get updated automatically whenever you type in new text, move a slider, change the window size and so on. It works the other way around, too. If you modify the 'Position' property with set( handles.edit1, 'Position', [20 20 100 30]), then the widget is automatically moved and re-sized to the specified position.