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.
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();
I used Matlab GUIDE to create a GUI.
It is displayed mid-screen.
How can I position it at the top of the screen; so that the top edge of the GUI window is at top of screen.
It will be used on different Windows 7 computers with different screen resolutions.
I tried to set hObject.Position(2) but it doesn't do what I want.
I think the simplest way would be to use movegui in the OpeningFcn of your GUI with the appropriate argument, i.e. using either 'north', 'northeast' or 'northwest'.
The calling syntax is quite simple, using the handles to the figure created. In GUIDE, the default name for figures is "figure1", so in your case the code would look like this (unless you changed the figure's name):
movegui(handles.figure1,'northwest') %// or whatever
Note that movegui calls the following 3 functions to get the screen size and monitor positions/units:
screensize = get(0, 'ScreenSize');
monitors = get(0,'MonitorPositions');
old0units = get(0, 'Units');
So you could do the same to make the calculations yourself in order to place the figure precisely where you want if the above solution is not sufficient for you.
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 try to remove the Matlab-given units from this plot but I don't find a way:
figure(1)
hold on
set(gcf,'PaperUnits','centimeters',...
'PaperSize',[15 9],...
'PaperPosition',[0 0 15 9]);
pzmap(LB); sgrid; grid on; axis equal;
title('');
xlabel('\sigma [rad/s]')
ylabel('\omega [rad/s]')
hold off
After that commands the xlabel looks like this: \sigma [rad/s] (seconds^-1). The seconds comes with pzmap. How can I remove them?
I found, some strange behavour:
If generate code by the figure plot manager I get this:
% Create xlabel
xlabel('\sigma [rad/s] (seconds^{-1})','Units','pixels');
Why???
Now I get it - without pzmap/pzplot
pol = pole(sys)
figure(1)
plot(real(pol(:)),imag(pol(:)),'x')
title('');
xlabel('\sigma [rad/s]');
ylabel('\omega [rad/s]');
sgrid
pzmap is a high-level convenience function, but it's not the best choice for this (it's also stored in a folder of obsolete functions in R2013a, so it may get marked for official removal in the future). Instead, let's create an example plot using pzplot directly instead of pzmap. This is still a plot function that does a lot under the hood, but it returns a handle, h, to the plot:
sys = rss(3,2,2);
h = pzplot(sys);
sgrid;
axis equal;
We can via the options of a pzplot with getoptions:
p = getoptions(h)
To set the labels and units as you desire, you might try this, using setoptions:
p.Title.String = '';
p.XLabel.String = '\sigma';
p.YLabel.String = '\omega';
setoptions(h,p);
I believe that the units of 'seconds-1' that the plot displays is equivalent to the 'rad/s' that you want to specify. I know that the two look is very different (I prefer being specific about radians myself), but that's a disadvantage of using such a plot function that tries to do everything for you. If you wanted to remove the default string or add another option, you'd likely have to do some low level hacking. An easier way around, might be to use the "Generate Code..." command ("Generate M-File..." in older versions") under the "File" menu in the figure's toolbar and edit the plot labels there (there's also a programmatic option for this on the File Exchange). Or you could output to postscript and edit that.
Alternatively, you can use pzoptions to create a list of options to pass to pzplot or pzmap (undocumented in the latter case):
p = pzoptions;
p.Title.String = '';
p.XLabel.String = '\sigma';
p.YLabel.String = '\omega';
sys = rss(3,2,2);
pzplot(sys,p);
sgrid;
axis equal;
You'll see that that for some reason the text size is much smaller in this case. pzplot and pzmap must set the font size to 10 themselves. You could easily do this.
Fore more on customizing this and related Control toolbox plots, see this article.
After intense low-level digging, there is actually a pretty simple way to override the default behavior.
p = pzplot(sys);
p.AxesGrid.XUnits = 'rad/s';
p.AxesGrid.YUnits = 'rad/s';
Changes appear to take effect immediately. I have even tried setting the value to nothing, i.e.
p.AxesGrid.XUnits = '';
and it effectively removes the annoying parenthesis with the units. Technically, matlab creates a custom-class element they store under the name AxesGrid in the resppack.mpzplot class instance, with some standard LTI-behavior. You can probably work around some stuff by "injecting" a script with the same name as one of the standard library functions, so that it will be called instead, and change things in there, but this is the closest I have come to removing those annoying units in a few lines.
As a side info, the AxesGrid object is initialized in
...\controllib\graphics\#resppack\#pzplot\initialize.m
should you want to check it out.
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);