I wish to add at least 3 customizable point ROIs on an axes in App designer and to store them in an array. Any idea how to make this code shorter and better that it will allow to add more than 3 point ROIs (without declaring several drawpoint) and still allow them to be moved on the image?
Code:
function StartButtonPushed(app, event)
imshow('peppers.png','Parent',app.ImageAxes);
roiPOC1 = drawpoint(app.ImageAxes);
PosPOC1=round(get(roiPOC1,'Position'))
roiPOC2 = drawpoint(app.ImageAxes);
PosPOC2=round(get(roiPOC2,'Position'))
roiPOC3 = drawpoint(app.ImageAxes);
PosPOC3=round(get(roiPOC3,'Position'))
drawnow;
end
Related
As the title states, I need to get a handle for my Matlab application. My class is derived from matlab.apps.AppBase and is app.UIFigure (if that matter, I'm still learning Matlab). My main goal is to change the mouse cursor to watch after a button is clicked and data is processed in the background.
I have tried:
set(gcf,'Pointer','watch')
But gcf is just empty, so it creates a new figure. I have also gotten all of the figures, using:
figs = findall(groot,'Type','Figure')
Which finds all of the figures I am using. I believe that I need to get the overall application figure and find the handle, but I am unsure how to do that.
There is no pointer property for uifigure; otherwise, you would be able to use app.UIFigure.Pointer = 'watch' as suggested by #CrisLuengo.
However, specially for uifigure MATLAB provides a nice looking and powerful progress bar uiprogressdlg. You can make it indeterminate with uiprogressdlg.Indeterminate = on;. I find this working pleasingly well.
Here is an example:
f=uifigure;
progressdlg=uiprogressdlg(f,'Title','Progress','Message', 'Doing something please wait', 'Indeterminate','on');
pause(10); % Run your algorithm.
% Delete the progress bar after work done.
progressdlg.delete();
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.
I have several GUI's which I would like to combine into one "master" GUI where I could select all the GUI's in different tabs. Is there a way to do it, without building the GUI from scratch?
Just to make it clear:
GUI 1 Data Loading
GUI 2 Data Preprocessing
GUI 3 Data Analysis
Master GUI=Should have 3 tabs with the same layout etc. like the existing GUI's
Update:
I tried the GUI Layout Toolbox which can be used to create tabs. But how do I now include my already existing GUI's into each tab?
f = figure();
p = uiextras.TabPanel();
uicontrol( 'Parent', p);
uicontrol( 'Parent', p);
uicontrol( 'Parent', p);
p.TabNames = {'Data Loading', 'Data Preprocessing', 'Data Analysis'};
p.TabSize = 100;
Update 2:
Are there any other options to combine multiple GUI's?
IMHO, this pretty much depends on the implementation of the individual guis.
If all GUIs make use of guidata and properties of the parent figure (of which there will be only one after the combination), this can quickly become impossible or at least messy without reworking all GUIs.
Another possibility would be to dock the figures into one desktop-group.
This way each individual GUI would be kept isolated and doesn't need changes in its implementation.
See e.g.
http://www.mathworks.nl/matlabcentral/fileexchange/18106-manage-and-dock-figures-into-group
for an example on how to dock figures into one desktop-group.
EDIT:
A quick&dirty example:
function dockTest()
GROUPNAME = 'MyGUIs';
desktop = com.mathworks.mde.desk.MLDesktop.getInstance();
group = desktop.addGroup(GROUPNAME);
desktop.showGroup(GROUPNAME,1);
% create some dummy-figures:
for i=1:2
figureList(i) = figure('name', ['GUI ', num2str(i)],...
'numbertitle','off');
end
% dock figures in list:
for i=1:numel(figureList)
f = figureList(i);
jf = get(handle(f), 'JavaFrame');
jf.setGroupName(GROUPNAME);
set(f, 'WindowStyle', 'docked');
end
end
You should be able to simply make figureList (and maybe GROUPNAMEas well) be an argument to this function, hence passing it all figure-handles you want to dock into a group.
You don't need a toolbox for this.
I guess I should note that this is all based on undocumented features.
I usually play around with this sort of things by making heavy use of methodsview on the individual java objects involved.
Try the GUI Layout Toolbox from the File Exchange, it allows tabbed GUIs, which are not supported out of the box in MATLAB. There will probably be some re-writing of your existing GUIs to make them work with the GUI Layout Toolbox used for the main GUI, but hopefully this should be minimal.
One way to combine several GUI is to manipulate their visibility with an extra GUI.
create a main GUI with 3 buttons
in the opening function OpeningFcn, call your 3 gui and save their handles in the workspace with
STATE(1) = dataLoading;
STATE(2) = dataProcessing;
STATE(3) = dataAnalyzing;
assignin('base', 'STATE', STATE);
%make the first one visible
set(STATE(1),'Visible','on');
set(STATE(2),'Visible','off');
set(STATE(3),'Visible','off');
in pushbutton_Callback, retrieve STATE and set a visibility property
STATE = evalin('base', 'STATE');
set(STATE(1),'Visible','off');
set(STATE(3),'Visible','off');
set(STATE(2),'Visible','on');
Hi everyone and thanks in advance for all your help.
I'm currently working on a UI in matlab that includes 4 differents axes to show various info. Basicly, I have MRI data (so 3D data) that I want to show. I use 1 axe to show 3 perpendicular plane that split the data at its center (axeMain), and 3 other axes that shows the planes individually (axeX,axeY and axeZ). I have a main axe on wich I want to make rotations possible (only on the main axis system) and I want to be able to select coordinate on the 3 other axe (those with 1 plane only). I also unable translations but that is out of scope for my problem.
So basicly, I have no problem selecting my coordinates (using the buttondownfcn on my planes) on all of the 3 axes and I also have no problem using rotate3D on the mainAxe. HOWEVER, if I try to have both to work at the same time, the buttondownfcn doesn't work anymore. I don't understand why it's doing this (I have some ideas but that's about it) and I have no idea how to work around it. Basicly my code for those functions are like this :
rotate3d(handles.axisMain);
%some other code, setting up other UI stuff
%allow selection on the 3 static plains.
set([handles.axeX,handles.axeY,handles.axeZ], 'buttondownfcn', #getCoord);
So my question is basicly : why wont those 2 functions don't work together and how to work around that problem, ideally with minimal code change?
Thanks.
EDIT : this is a print screen of my current interface. I want to be able to select coordinate using ONLY on the 3 last axes (containing only 1 plane in each of them). I also want to be able to rotate images ONLY on the first axe (the one with 3 planes). Hope this clarify.
I would also like to note this : following my tests, I found that the mouse click would not raise at all if the rotate3D is activated. The problem is not in the logic I use to get the coordinates itself, but in the click event not being fired.
Also, I am aware that the event is not on the surface that I try to print. The actual code is like this :
set(h, 'buttondownfcn', #getCoord);
set(h,'HitTest','on');
where h is the handle of a surface and each surfaces are processed this way.
I have found the exact solution!
Exploring the code for rotate3d(hAxe,'on') , i have found that they key line is getuimode(hFig,'Exploration.Rotate3d') wich returns uitools.uimode that contains ButtonDownFilter and ModeStateData methods.
Finally i have solved the problem in the following way:
rotate3d(hAxe,'on')
uiMode = getuimode(hFig,'Exploration.Rotate3d');
uiMode.ButtonDownFilter = #mycallback;
where:
hAxe is the handle to the axes object
hFig is the handle to the figure object
#mycallback is the callback that lets buttondownfcn and rotate3d works together as in the example of Matlab's help
So, you have to tag the object that you want to not be ignored:
set(hAxe,'tag','DoNotIgnore')
And write the callback:
function [flag] = mycallback(obj,event_obj)
% If the tag of the object is 'DoNotIgnore', then return true
objTag = obj.Tag;
if strcmpi(objTag,'DoNotIgnore')
flag = true;
else
flag = false;
end
maybe
set(handles.axisMain, 'buttondownfcn', #getCoord);
I've writtend a GUI function in MATLAB R2009b which makes use of the IMRECT function. I need to make sure this GUI also works in MATLAB R2007b: since this release the IMRECT function has undergone extensive changes. I have two question:
1 - in the new (R2009b) IMRECT, a method GETCOLOR is defined which allows to get the color which was selected by the user using the scroll menu. Is there a way to mimic this behavior for the old (R2007b) function?
2 - in MATLAB R2009b I can use WAIT after using IMRECT as follows:
h = imrect(axhandle);
wait(h);
this allows to wait unitl the user as correctly placed his/her rectangle and has double click to confirm the choice. Is there anything analogous that can be used with IMRECT from R2007b?
Unfortunately, you need a workaround for both functions.
Here is one way to do it:
%# Create a figure and some points
fh = figure;plot(rand(10,1),rand(10,1),'.')
ah = gca;
%# this allows the user to place the rectangle. However, the code resumes
%# as soon as the rectangle has been drawn
rh = imrect(ah,[]);
%# Create a dialog to have the possibility to uiwait
wh = warndlg('Please close this dialog once you are done adjusting your rectangle');
uiwait(wh)
%# Get the color of the rectangle
rectKids = get(rh,'Children');
rectangleColor = get(rectKids(1),'Color');
You can use verLessThan to check for the Matlab version in order to get the proper functionality. However, if there are users who'll use the code both on 2007b and 2009b, I suggest you leave the dialog box in for everyone, so that they don't get confused when they switch.