MATLAB - Using radio buttons to change units for a graph - matlab

I am very new to Matlab and I am trying to create a GUI from an equation. I have to make it so I can change the units by clicking on radio buttons.
T=MIN:10:MAX
P=10.^(A-B./(C+T));
plot(T,P)
xlabel('Temperature')
ylabel('Pressure')
This is how I plot the graph and to input the constant for A, B, C, MIN and MAX, I did this.
contents = cellstr(get(hObject,'String'));
popChoice = contents{get(hObject,'Value')};
if (strcmp(popChoice,'Acetic Acid'))
A=8.021;
B=1936.01;
C=258.451;
MIN=18
MAX=118
and then
assignin('base','A',A);
assignin('base','B',B);
assignin('base','C',C);
assignin('base','MIN',MIN);
assignin('base','MAX',MAX);
I did this for about 15 more compounds. Then I assigned the constants to the workspace. The graph works for all the compounds when I change them in the pop up menu but I don't know how to use the radio buttons to change the units of both T and P. I am very new to this. Thank you.

Related

enable context menu for specific cell or item in uitable or uilistbox in matlab

I created a uitable (new version using appdesigner) in MATLAB and wanted to support right clicking on cells and showing a cell specific context menu. Much to my surprise there seemed to be no way to support this.
The context menu only seems to trigger with right click on the uitable, but there is no way of knowing which cell was selected (I think, maybe not?). I created a workaround where I left clicked to select a cell, and during that selection I right clicked using a Java Mouse robot to trigger the context menu. This is super ugly but sort of works. Except, if you need to bring up the menu twice on the same cell. Apparently the cell selected callback only fires once for the cell, until a new cell is selected. I tried literally putting two tables in the same spot and upon selecting one toggling to the other, but the memory of cell selection is table specific, so this only worked for two clicks before both tables had been clicked on the same cell, and toggling visibility back to the first resulted in the cell selection callback not firing (since the cell had not changed) . I tried various approaches to try and deselect the cell (disable/enable, visibility change, data change, etc.), but the cell selection callback never changed.
I even tried having duplicate columns, where the goal was to hide a column, where normally columns 1 and 2 would be visible (column 3 out of view due to size), and then on clicking on column 2, column 2 would hide itself (0 width) and column 3 (an exact duplicate) would move into its place, thus seeming to the user like multi-clicking was supported. Unfortunately I can't set the column width to 0 -- or rather, setting it to 0 doesn't completely hide the column. Instead there seems to be some minimal width to the column and the whole thing looked awful.
I wanted to do something similar with a listbox (right click support), but again I couldn't figure out how to identify where I was right clicking. I eventually settled on left clicking on a listbox and using the mouse robot approach to right click to bring up the context menu. Unlike the uitable, it was fairly easy to clear the selection on the listbox (set listbox.Value = {}). However, I strongly dislike the left click instead of right click approach and I'd rather have multiple columns.
Any suggestions would be much appreciated!!!
So I found an approach that is better than using a robot. I had tried this but was missing a critical portion which I will describe below.
Upon selecting a row in the table, the open command can be used to launch a context menu. My problem was that I didn't know where to launch the menu. I tried CurrentPoint for the figure, but it was 0,0 (or in general not valid)
Here's the current documentation for CurrentPoint:
Current point, returned as a two-element vector. The vector contains
the (x, y) coordinates of the mouse pointer, measured from the
lower-left corner of the figure. The values are in units specified by
the Units property.
The coordinates update when you do any of the following:
Press the mouse button within the figure.
Release the mouse button after pressing it within the figure.
Press the mouse button within the figure, and then release it outside
the figure.
Rotate the scroll wheel within the figure.
Move the mouse within the figure (without pressing any buttons),
provided that the WindowButtonMotionFcn property is not empty.
If the figure has a callback that responds to mouse interactions, and
you trigger that callback faster than the system can execute the code,
the coordinates might not reflect the actual location of the pointer.
Instead, they are the location when the callback began execution.
If you use the CurrentPoint property to plot points, the coordinate
values might contain rounding error.
Here's the critical line again:
"Move the mouse within the figure (without pressing any buttons), provided that the WindowButtonMotionFcn property is not empty."
So when a selection of a cell happens, the CurrentPoint is not valid. However, if we simply define a WindowButtonMotionFcn, then it is!
So the general idea is to have a callback for the table when a cell is selected (SelectionChangedFcn) and to set a dummy callback for WindowButtonMotionFcn
The final point is that a context menu can be launched with the open function if you specify a given location to launch it at. This is different from attaching it to an object and having it automatically launch on right click.
Here's some example code. If you comment out the callback for windows motion then the whole thing doesn't work! Unfortunately it is a left click for targeting the cell but at least it avoids the non-sense I was using with a java robot right click.
classdef wtf < handle
properties
h %struct, this was an appdesigner handle
cm %context menu
end
methods
function obj = wtf()
h = struct;
h.UIFigure = uifigure();
h.UITable = uitable(h.UIFigure);
obj.h = h;
obj.h.UITable.CellSelectionCallback = #obj.tableCall;
%obj.h.UITable.SelectionChangedFcn = #obj.tableCall;
%Some data ...
s = struct;
s.a = (1:4)';
s.b = (5:8)';
obj.h.UITable.Data = struct2table(s);
%Our context menu
cm = uicontextmenu(obj.h.UIFigure);
m = uimenu(cm,'Text','Menu1');
obj.cm = cm;
%WTF ... without this we don't get a valid CurrentPoint
obj.h.UIFigure.WindowButtonMotionFcn = #obj.mouseMove;
end
function tableCall(obj,x,y)
%y - event info
%x - impacted object
cp = get (obj.h.UIFigure, 'CurrentPoint');
open(obj.cm,cp(1),cp(2));
selected_cell = y.Indices;
%selected_cell = y.Selection;
x.Selection = []; %allows reselecting same cell without
%needing to select another cell first
%Now we can run something on the context menu
%that targets the selected cell
end
function mouseMove(obj,x,y)
%we could store a point here
end
end
end

In app designer, how do I 'hold' my plot when switching between drop-down menu values?

In app designer, I have multiple drop-down menus that allow the user to select data values that are then plotted. The first time the 'plot' button is clicked, there are no issues with plotting only one selection from a menu, or plotting multiple data values from multiple drop-down menus. However, if the user changes a drop-down menu value, only one of the values is plotted unless the 'plot' button is clicked again.
I have tried multiple solutions, including using hold in various ways or by clearing the axis during the 'plot' button's initial run (e.g., by using cla) to essentially reset the 'plot' button function.
Sample code:
SelectedMetric = app.OsteoDropDown.Value;
[ColumnValue] = OsteometricFunc(SelectedMetric);
PopSelectionA = app.PopulationA.Value;
[RowValue] = PopulationAFunc(PopSelectionA);
x = 1:length(RowValue);
y = OsteoData(RowValue,ColumnValue);
%hold(app.UIAxes);
scatter(app.UIAxes,x,y,'g');
PopSelectionB = app.PopulationB.Value;
[RowValue] = PopulationAFunc(PopSelectionB);
x = 1:length(RowValue);
y = OsteoData(RowValue,ColumnValue);
hold(app.UIAxes);
scatter(app.UIAxes,x,y,'r');
First instance of clicking the 'Plot' button does everything correctly:
Second instance of clicking 'Plot' button, wherein only the drop-down for 'Population II' has been changed. The plot for 'Population I' is no longer visible, though it should be:
Clicking the 'plot' button again correctly plots all values, however:
How do I resolve this so that switching a single drop-down menu (or multiple drop-down menus, for that matter) automatically plot everything for all drop-down menu values?

How can I add waitbar in the current GUI window MATLAB?

I am having a GUI figure, which contains some buttons, I want to show waitbar on the same GUI window on which buttons are placed, I tried different solutions but in vain. e.g when user clicks on button it starts showing me waitbar on left bottom side of the figure.
You could try to add a java waitbar in your figure.
Put this in the OpeningFcn
PB=javaObjectEDT(javax.swing.JProgressBar);
javacomponent(PB,[10,10,200,20],gcf); %put at bottom part of the current figure
set(handles.output.Children(1),'Tag','first_bar'); %make sure you can find it back
In the callback of any function you can then set the bar to a value between 0 and 100 using this code:
h=findobj(handles.output.Children,'Tag','first_bar');
set(h.JavaPeer,'Value',rand(1)*100)
You can make it visible or invisible just as you would any GUI object in Matlab using
h=findobj(handles.output.Children,'Tag','first_bar');
set(h,'visible','off');
Here you can find details about the JProgressBar . For example using this you get a string with the progress inside the bar.
h=findobj(handles.output.Children,'Tag','first_bar');
set(h.JavaPeer,'StringPainted',1)

Matlab update plot in one GUI based on activity in second GUI

In one GUI (viewer) I have an image that shows a 2D slice through a 3D image cube. A toolbar button opens a second GUI (z-profile) that plots a 2D graph showing the z-profile of one pixel in the image cube. What I want is to be able to update this plot dynamically when a different pixel is clicked in the original viewer GUI. I've looked in to linkdata but I'm not sure if that can be used to link across two GUIs. Is there a simple way to do this without re-creating the second GUI each time a new pixel is clicked and feeding in the new input location?
You can definitely doing it without recreating the second GUI every time.
Without knowing your specific code I would say that you should store a reference to the second GUI in the first GUI, then in a callback for clicking a pixel in the first GUI, change data in the second GUI via the stored reference (e.g. figure handle). You can store arbitrary data in a figure, for example by using function guidata. A bit of code.
...
figure2 = figure();
figure1 = figure('WindowButtonDownFcn',#myCallback);
guidata(figure1, figure2);
...
function myCallback(obj,eventdata)
figure2 = guidata(obj);
...
Even easier but a bit more error-prone would be to use global variables for storing the references.

Two figures in two different files - how to run first fig from the second one?

I have two figs in two different files.
By clicking a button on first fig I want to show the second one... how to do this? is it possible?
If YES than how to exchange with data between two figures?
There are a number of ways to share data among GUIs. In general, you need to somehow make the graphics handle(s) from one GUI available to the other GUI so it can get/set certain object properties. Here's a very simple example that involves one GUI creating another and passing it an object handle:
function gui_one
hFigure = figure('Pos',[200 200 120 70],... %# Make a new figure
'MenuBar','none');
hEdit = uicontrol('Style','edit',... %# Make an editable text box
'Parent',hFigure,...
'Pos',[10 45 100 15]);
hButton = uicontrol('Style','push',... %# Make a push button
'Parent',hFigure,...
'Pos',[10 10 100 25],...
'String','Open new figure',...
'Callback',#open_gui_two);
%#---Nested functions below---
function open_gui_two(hObject,eventData)
gui_two(hEdit); %# Pass handle of editable text box to gui_two
end
end
%#---Subfunctions below---
function gui_two(hEdit)
displayStr = get(hEdit,'String'); %# Get the editable text from gui_one
set(hEdit,'String',''); %# Clear the editable text from gui_one
hFigure = figure('Pos',[400 200 120 70],... %# Make a new figure
'MenuBar','none');
hText = uicontrol('Style','text',... %# Make a static text box
'Parent',hFigure,...
'Pos',[10 27 100 15],...
'String',displayStr);
end
After saving the above code to an m-file, you can create the first GUI by typing gui_one. You will see a small figure window with an editable text box and a button. If you type something in the text box, then hit the button, a second GUI will appear next to it. This second GUI uses the handle to the editable text box that is passed to it from the first GUI to get the text string, display it, and clear the string from the first GUI.
This is just a simple example. For more information on programming GUIs in MATLAB, take a look at the MathWorks online documentation as well as the links in the answers to this SO question.