You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
How to make an interactive panel for the user to chose among several options
3 views (last 30 days)
Show older comments
Hi
I want to have a panel (User Interface) with 3-4 different cropping image options and the user shall be able to chose the size he likes.
For instance, I could have subplot(2,2,1-4) four different cropping window sizes, of an image.
For example, a big cropping area of the image, a smaller one by 30%, an even smaller one by 50% of the original image, and a finally a very thin and slight strip of image.
By mouse clicking, the user can chose the appropriate cropping image window size for further processing.
Is it possible to do that?
Thanks
Accepted Answer
Walter Roberson
on 2 Feb 2019
Yes. You could configure uicontrol style 'radio' in a uibuttongroup, or you could configure a single uicontrol style 'listbox' or 'popup' that had the four options configured.
21 Comments
Stelios Fanourakis
on 3 Feb 2019
@Walter. Can you please give me an example code of how to handle the uicontrol for 'radio' style button for two options?
Thanks
Walter Roberson
on 3 Feb 2019
Look at the documentation for uibuttongroup. It has a complete example for 3 buttons.
The code there would probably be best suited for the case where the user clicking on one of the buttons was intended to trigger an action. If no action is to be triggered then leave the SelectionChangedFcn as the default [] but then in your routine that is intended to have action.
sel = handles.YourButtonGroupTagGoesHere.SelectedObject;
and that will either be [] if no buttons are selected, or will be the handle of the uicontrol that is pushed. You can then
sel.String
to get the associated string. Or you could have configured UserData for each uicontrol style radio to give some value you needed, such as the limits to resize to;
curimage = handles.YourInputImageDisplayHandleGoesHere.CData;
crop_to = sel.UserData;
newimage = imcrop(curimage, crop_to);
set(handles.YourOutputImageDisplayHandleGoesHere.CData, newimage);
Stelios Fanourakis
on 3 Feb 2019
@Walter
I got this code from uibuttongroup documentation. How do I link the options with the images?
bg = uibuttongroup('Visible','off',...
'Position',[0 0 .2 1],...
'SelectionChangedFcn',@bselection);
r1 = uicontrol(bg,'Style',...
'radiobutton',...
'String','Option 1',...
'Position',[10 350 100 30],...
'HandleVisibility','off');
r2 = uicontrol(bg,'Style','radiobutton',...
'String','Option 2',...
'Position',[10 250 100 30],...
'HandleVisibility','off');
% Make the uibuttongroup visible after creating child objects.
bg.Visible = 'on';
Walter Roberson
on 3 Feb 2019
Edited: Walter Roberson
on 3 Feb 2019
bg = uibuttongroup('Visible','off',...
'Position',[0 0 .2 1],...
'Tag', 'BG1');
r1 = uicontrol(bg,'Style',...
'radiobutton',...
'String','Option 1',...
'Position',[10 350 100 30],...
'HandleVisibility','off');
r2 = uicontrol(bg,'Style','radiobutton',...
'String','Option 2',...
'Position',[10 250 100 30],...
'HandleVisibility','off');
% Make the uibuttongroup visible after creating child objects.
bg.Visible = 'on';
together with some button, say 'Do_Plot', that is intended to activate the plotting instead of just selecting options:
function Do_plot(hObject, event, varargin)
bg = findobj(gcf, 'Tag', 'BG1');
sel = bg.SelectedObject;
if isempty(sel)
return; %no buttons selected
end
sel_string = sel.String;
switch sel_string
case 'Option 1'
do something appropriate
case 'Option 2'
do something appropriate
end
end
Stelios Fanourakis
on 3 Feb 2019
@Walter
I tried this
function Do_plot(hObject, event, varargin)
bg = findobj(gcf, 'Tag', BG1');
sel = bg.SelectedObject;
if isempty(sel)
return; %no buttons selected
end
sel_string = sel.String;
switch sel_string
case 'Option 1'
IMg = double(cropped)
case 'Option 2'
IMg = double(J)
end
end
Since, I want for Option 1 to be the first image and Option 2 the second image taken for post processing but it doesn't seem to work.
bg = uibuttongroup('Visible','off',...
'Position',[0 0 .2 1],...
'Tag','BG1', @Do_plot);
r1 = uicontrol(bg,'Style',...
'radiobutton',...
'String','Option 1',...
'Position',[10 350 100 30],...
'HandleVisibility','off');
r2 = uicontrol(bg,'Style','radiobutton',...
'String','Option 2',...
'Position',[10 250 100 30],...
'HandleVisibility','off');
% Make the uibuttongroup visible after creating child objects.
bg.Visible = 'on';
Still, it won't work.
Can you spot the error?
Error using hguibuttongroup
Incorrect number of input arguments.
Error in usev0buttongroup (line 9)
result = builtin('hguibuttongroup', varargin{:});
Error in uibuttongroup (line 34)
h = usev0buttongroup(varargin{:});
Error in ruller (line 125)
bg = uibuttongroup('Visible','off',...
Walter Roberson
on 3 Feb 2019
bg = uibuttongroup('Visible', 'off',...
'Position', [0 0 .2 1],...
'Tag', 'BG1', ...
'SelectionChangeFcn', @Do_plot);
Stelios Fanourakis
on 3 Feb 2019
Is it correct the way I call it?
Img = double(bg);
bg should be either Option 1 or Option 2.
But I get the error
Error using contour (line 48)
Z must be at least a 2x2 matrix.
Error in ruller (line 195)
hold on,[c,h] = contour(phi,[0 0],'r','linewidth',1); hold off
Stelios Fanourakis
on 3 Feb 2019
It's not working either using this
bg = uibuttongroup('Visible', 'off',...
'Position', [0 0 .2 1],...
'Tag', 'BG1', ...
'SelectionChangeFcn', @Do_plot);
If I call this
Img = double(bg);
Walter Roberson
on 3 Feb 2019
I already provided you with the code for Do_plot that showed how to determine which of the two buttons was pressed.
Button groups do not have a numeric value associated with them. As far as uibuttongroup is concerned, the buttons are not ordered, and there is no index number property associated with the button group. You cannot ask directly ask the button group "is the second button pressed" ?
The closest you can get to that is something like,
Img = length(bg.NodeChildren) + 1 - find(ismember(bg.NodeChildren, bg.SelectedObject));
note that despite the variable name Img, this will not be an image but instead will just be an index telling you which button was pressed, compared to the order that you added the children.
Stelios Fanourakis
on 3 Feb 2019
I want to have the appropriate image selected for further postprocessing.
User can chose whatever of two images, using the radiobuttons.
How do I do that?
Stelios Fanourakis
on 3 Feb 2019
I don't understand the last line you sent me.
Where am I supposed to stick it?
Walter Roberson
on 3 Feb 2019
function Do_plot(hObject, event, varargin)
bg = findobj(gcf, 'Tag', 'BG1');
sel = bg.SelectedObject;
if isempty(sel)
return; %no buttons selected
end
sel_string = sel.String;
switch sel_string
case 'Option 1'
Img = image associated with option 1
case 'Option 2'
Img = image associated with option 2
end
now do something with Img such as displaying it
end
Stelios Fanourakis
on 4 Feb 2019
Edited: Stelios Fanourakis
on 4 Feb 2019
now do something with Img such as displaying it
In this case, I need to assign Img as the input for a series of post processing algorithm such the automated segmentation.
That needs to be assigned earlier as the Do_plot function goes to the end of the script and the active contour function is earlier that's why the series goes like this
bg = uibuttongroup('Visible','off',...
'Position',[0 0 .2 1],...
'Tag', 'BG1');
r1 = uicontrol(bg,'Style',...
'radiobutton',...
'String','Option 1',...
'Position',[10 350 100 30],...
'HandleVisibility','off');
r2 = uicontrol(bg,'Style','radiobutton',...
'String','Option 2',...
'Position',[10 250 100 30],...
'HandleVisibility','off');
% Make the uibuttongroup visible after creating child objects.
bg.Visible = 'on';
Img = bg; %%% ??? Here needs for the Option to be assigned as Img, either Option1 or Option2. Later on follows the script...
..%% for the active contour and at the end comes the Do_plot.
I still cannot make it run
Walter Roberson
on 4 Feb 2019
Stelios Fanourakis
on 6 Feb 2019
bg = uibuttongroup('Visible','off',...
'Position',[0 0 .2 1],...
'SelectionChangeFcn',@Do_plot);
r1 = uicontrol(bg,'Style',...
'radiobutton',...
'String','Option 1',...
'Position',[10 350 100 30],...
'HandleVisibility','off');
r2 = uicontrol(bg,'Style','radiobutton',...
'String','Option 2',...
'Position',[10 250 100 30],...
'HandleVisibility','off');
% Make the uibuttongroup visible after creating child objects.
bg.Visible = 'on';
Img = double(bg);
And later, further down the code as the last function
function Do_plot(hObject, event, varargin)
bg = findobj(gcf, 'Tag', 'BG1');
sel = bg.SelectedObject;
if isempty(sel)
return; %no buttons selected
end
sel_string = sel.String;
switch sel_string
case 'Option 1'
Img = croppedImage;
case 'Option 2'
Img = J;
end
Img = double(Img);
end
Walter Roberson
on 6 Feb 2019
That code does not define J or croppedImage. Are those defined as functions, or is the Do_plot routine a nested routine using shared variables?
Your code makes not attempt to store Img. Is this in a nested routine using shared variables?
Img = double(bg);
That line will create the old numeric style graphics handle from the object handle bg, such as if you needed some compatability with code written for R2014a or earlier that stored graphics handles in numeric arrays.
I recommend that you read what someone wrote to you over in
Stelios Fanourakis
on 8 Feb 2019
Thanks Walter. Please, do let me know whether you can actually solve my problem. Hope, you know what my problem is.
Walter Roberson
on 8 Feb 2019
The major problem is that you are not understanding the architecture of GUI systems.
GUI elements are mostly asynchronous. You do not create a GUI element and then expect it to return a value by referring to it right afterwards: GUI elements are not subroutines. You need to provide an opportunity for the user to interact with the element, and for the user to trigger an event that your code reacts to through a callback.
- create graphics elements (possibly by loading .fig)
- if you have a backing MATLAB interactive session, you can return to the MATLAB prompt at this point if you want, leaving the GUI figure up; otherwise, uiwait() or waitfor() the GUI figure to be closed, after which you would close the GUI figure
- User moves and clicks and whatever, eventually triggering a callback that you have configured. Each callback runs, does whatever is appropriate, and the returns back to whatever the program was doing (possibly waiting, possibly processing a different routine.)
- if the callback is for chosing settings, then do whatever validation needed and when satisfied, either leave the GUI elements configured that way to be retrieved later or else store the results into a location you can get at afterwards; Share . Sometimes it makes sense that choosing a setting should enable further GUI elements, so you might either create those elements or have set them to be visible or enabled if you had created them before. For example if you were doing a polynomial fitting routine, then the 'FIT' action button should be disabled until the data has been chosen and the user has entered a polynomial degree.
- if the callback is for chosing files, then do whatever validation is needed and when satisfied, either leave the GUI elements configured that way to be retrieved later or else store the file name in a location you can get at afterwards or else load the file and store the useful information from it into a location you can get at afterwards, possibly displaying something as you go; Share. Sometimes it makes sense that choosing a file should enable further GUI elements, so you might either create those elements or have set them to be visible or enabled if you had created them before. For example if you were doing a polynomial fitting routine, then the 'FIT' action button should be disabled until the data has been chosen and the user has entered a polynomial degree.
- if the callback is something you have designed to signal that action should be taken, then gather the necessary settings and data from GUI elements or from the information you saved in the other callbacks, and process the data, outputting appropriate results, and possibly saving intermediate results into locations that you can get at afterwards; Share . Sometimes it makes sense that performing an action should enable further GUI elements, so you might either create those elements or have set them to be visible or enabled if you had created them before. For example if you were doing a polynomial fitting routine, then a request to display an optional error plot should be disabled until the user has run the fitting; if you were doing steganography, then the "Extract" action should possibly be disabled until the "Embed" action has been run (*or* the user has done a Load Embedded Image action.)
There is a bit of room for variation. An executing program can force a graphics interaction to be done in sequence by:
- create graphics elements inside a figure that was created as 'WindowStyle', 'modal', or make pre-created graphics elements visible
- uiwait() or waitfor() that figure to close or for a particular property of a graphics element to change or to become a particular value. With the 'modal' figure in effect, the user will not be permitted to interact with any other figure in the mean time
- destroy the graphics elements or make them hidden again to wait for next time
Every questdlg or inputdlg call (and even warndlg and errordlg) work the way just described: they create a new modal figure, put up some content in it, uiwait() for the user to click a button or close the figure, and then delete the temporary figure if it still exists. Such things have their uses -- but this sequence is not how permanent UI elements such as radio buttons are handled -- those are handled by the "sit and do nothing until the user triggers a callback" process I describe above.
Stelios Fanourakis
on 9 Feb 2019
@Walter. Sorry but your last explanation is too much complicated for me to understand. Can you please explain it with fewer words?
Also, what is wrong with this code I use? I probably have limited knowledge on GUI and how they work. That's why I am here, so I can learn from my mistakes.
bg = uibuttongroup('Visible','off',...
'Position',[0 0 .2 1],...
'SelectionChangeFcn',@Do_plot);
r1 = uicontrol(bg,'Style',...
'radiobutton',...
'String','Option 1',...
'Position',[10 350 100 30],...
'HandleVisibility','off');
r2 = uicontrol(bg,'Style','radiobutton',...
'String','Option 2',...
'Position',[10 250 100 30],...
'HandleVisibility','off');
% Make the uibuttongroup visible after creating child objects.
bg.Visible = 'on';
Img = bg; %%% This is the image I need to define whether Option1 = croppedImage, or Option2 = J; CroppedImage and J are two different images.
And the function Do_plot that follows in the end of the script.
function Do_plot(hObject, event, varargin)
bg = findobj(gcf, 'Tag', 'BG1');
sel = bg.SelectedObject;
if isempty(sel)
return; %no buttons selected
end
sel_string = sel.String;
switch sel_string
case 'Option 1'
bg.Value = croppedImage;
case 'Option 2'
bg.Value = J;
end
bg= double(bg);
end
More Answers (0)
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)