Use uibutton push to use a function and change a variable value

32 Views Asked by At

I have a problem I do not find a solution to (or maybe I just did not understand it elsewhere on the website...).

Here is my problem: I use a GUI as a uifigure and uibutton inside. When the uibutton is pressed, it calls a function that calculates a curves with input agruments and displays it in the uifigure. The idea of the interface is to press buttons to change variables value and observe the effect on the curve in the display section. So, in the same time than the display, I need to change a variable value in the main script when the button is pushed. My problem is that I cannot find a way to change this variable value at the same time the curve is calculated and displayed.

Here is the script (I simplified it but this gives an idea):

tp = 1;

gui_fig = uifigure('Position',[100 100 1300 700]);

p = uipanel(gui_fig,'Position',[10 10 1000 680]);
p.AutoResizeChildren = 'off';

Btntp_min = uibutton(gui_fig, ...
    "Text","-1%", ...
    "fontsize",14,"fontweight",'bold', ...
    "Position",[1060 475 100 30], ...
    "ButtonPushedFcn", @(src,event) Button_tp_min(p,tp));   

function Button_tp_min(ax,tp)
    tp = tp*0.99; % Effect of button        
    bx1 = subplot(2,1,1,'parent',ax);
    plot(bx1,1,tp,'o')
end

In this script, the point is to reduce by 1% the value of tp each time the button is pressed. It works the first time, but the reference value keeps being that in the main script. So how is it possible to modify this script so that the new value of tp is considered in the main script ?

1

There are 1 best solutions below

2
Hoki On

This is because the value of tp you initiate when you define the function is never updated, it is always 1 when the function Button_tp_min is fired by the button.

One way to have it work is to reserve a field in the application data of your figure. You can save and retrieve application data with the functions setappdata and getappdata respectively.

You first initiate the application data field when you create the figure and save the starting value of tp. Then each time the function Button_tp_min runs, it will:

  • Retrieve the handle of the top parent figure
  • Retrieve the application data field "TP" (and its value) from the figure handle
  • ... do what you want/need withthis value of tp, then
  • Save the modified value of tp in the the "TP" application data field.

By adding 4 lines to your code, using these application data, you now have a variable tp which is dynamic. Also note that since the variable tp is retrieved directly from within the Button_tp_min function, it is no longer necessary to provide it as input argument of the function.

tp = 1;
gui_fig = uifigure('Position',[100 100 1300 700]);

% save the initial [tp] in application data field named "TP"
setappdata(gui_fig,'TP',tp);

p = uipanel(gui_fig,'Position',[10 10 1000 680]);
p.AutoResizeChildren = 'off';

Btntp_min = uibutton(gui_fig, ...
    "Text","-1%", ...
    "fontsize",14,"fontweight",'bold', ...
    "Position",[1060 475 100 30], ...
    "ButtonPushedFcn", @(src,event) Button_tp_min(p));   

function Button_tp_min(ax)
    gui_fig = ancestor(ax,'figure','toplevel'); % retrieve top figure handle
    tp = getappdata(gui_fig,'TP');              % get the [tp] value
    tp = tp*0.99;                               % Modify [tp] value
    setappdata(gui_fig,'TP',tp);                % save the new [tp] value for next round
    % Display ...
    bx1 = subplot(2,1,1,'parent',ax);
    plot(bx1,1,tp,'o')
end

Just as a side note, your tp value will decrease by 1% of the previous value of tp (not by 1% of 100 as initialy). To give you an example:

tp(1) = 100;
for k=2:10
    tp(k) = tp(k-1)*.99;
end

Will give the first 10 values of tp as:

>> tp =
  100.0000
   99.0000
   98.0100
   97.0299
   96.0596
   95.0990
   94.1480
   93.2065
   92.2745
   91.3517

If that is what you wanted everything is fine, otherwise if you wanted a linear decrease (like [100 99 98 97 ...]), consider changing the line tp = tp*0.99; into tp = tp-1;