Change parent panel of GUIDE object - matlab

I have a Matlab GUIDE figure with nested panels. I also have control objects on top of the panels. Here's a notional example:
In order to align all of the checkboxes, they all need to be in the same control group. I want to move the checkboxes so that their parent is the main panel rather than one of the sub-panels. The sub-panels are just there for visual grouping and don't really have a functional value.
The object browser shows the relationships, but I see no way to change it. I've tried pasting the objects I want to move outside the sub-panel and dragging them back in, but they automatically get added to the sub-panel. If I paste outside of the sub-panel I can use the arrow keys to move them back in and the parent will stay the main panel, but that gets to be tedious.
How can I change the parent panel of a GUIDE control object?

Building the GUI with guide a possible solution could be:
add the main uipanel
add all the checkbox in the main `uipanel'
align them (e. g. by selecting some of them and then use the Align Objects tool on the guide toolbar
add the secondary uipanel over some of the checkbox. It will cover the `checkbox'
select the secondary uipanel
right-click on the mouse to pop-up the context menu
select the Send to Back option
If you want to create the GUI "programmatically" you can:
create a figure
add the main panel with uipanel
add the checkboxes with uicontrol setting the Style property to checkbox and the position property so that they will be placed in the main panel
add the secondary uipanel. Also in this case the secondary uipanel will mask the checkbox
push the secondary panel back using the uistack function
Thsi is a possible implementation
% Create the figure
figure
% Add the Main uipanel
p1=uipanel('units','normalized','position',[.1 .1 .5 .7],'title','Main Panel')
% Add come checkboxes
cb1=uicontrol('parent',p1,'style','checkbox','units','normalized', ...
'position',[.1 .7 .3 .1],'string','checkbox 1')
cb2=uicontrol('parent',p1,'style','checkbox','units','normalized', ...
'position',[.1 .6 .3 .1],'string','checkbox 2')
cb3=uicontrol('parent',p1,'style','checkbox','units','normalized', ...
'position',[.1 .5 .3 .1],'string','checkbox 3')
% Add the Secondary uipanel
p2=uipanel('parent',p1,'units','normalized','position',[.05 .4 .4 .5], ...
'title','Secondary Panel')
% Push the secondary uipanel back
uistack(p2,'bottom')
Hope this helps.
Qapla'

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

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)

How to switch between overlapping uipanels in Matlab GUI (Matlab2016)

I made a GUI with two uipanels, each containing 4 image axes.
I plotted different figures on each panel and want to switch between panels by a push button.
For this I used the following:
Initially, I set uipanel2 to 'visible' 'on' and uipanel3 to 'visible' 'off';
Then when I push 'push button' it checks if uipanel is 'on' and turns on and off respectively.
% Code:
set(handles.uipanel2,'visible','on');
set(handles.uipanel3,'visible','off');
% When I push 'push button':
if strcmp(get(handles.uipanel2,'visible'),'on')
disp('panel-2 onn switching it off')
set(handles.uipanel2,'visible','off');
set(handles.uipanel3,'visible','on');
elseif strcmp(get(handles.uipanel3,'visible'),'on')
disp('panel-3 onn switching it off')
set(handles.uipanel3,'visible','off');
set(handles.uipanel2,'visible','on');
end
It doesn't work as expected I don't see panels switching.
For displaying images I used code like this:
% Panel-2
axes(handles.RCC);
imshow(img_RCC,lims);
axes(handles.LCC);
imshow(img_LCC,lims);
axes(handles.RML);
imshow(img_RML,lims);
axes(handles.LML);
imshow(img_LML,lims);
% Panel-3
axes(handles.RCC_Orig);
imshow(img_RCC,lims);
axes(handles.LCC_Orig);
imshow(img_LCC,lims);
axes(handles.RML_Orig);
imshow(img_RML,lims);
axes(handles.LML_Orig);
imshow(img_LML,lims);
Update: I can only see the GUI panel on top being 'not visible' and switching to 'visible'. The panel on bottom I think is still there but I don't know how to make it come on top

how to manage uipanels matlab gui

I have 6 uipanels ,all same size overlapped one over another. I have to add buttons edit text to all the uipanels.but I can edit only 6th uipanel and all others are hidden.how can I make only one uipanel visible at a time so that I can easily add buttons and text to it. I have to add a push button in each panel which when clicked should show succeeding uipanel and hide previous uipanel.
For example,
I have a uipanel1 with a push button.when. I click the push button,it should show uipanel2 and hide uipanel1.
thanks
First of all you have to define yours uipanels as variables. For example, uipanel1 = uipanel(...); uipanel2 = uipanel(...)
So you can access easily to your six uipanel handles and put these handles in your button callback function.
Another solution would be to use the 'Tag' property for the uipanel in order to identify the uipanel. It may be longer but by using the findobj('Tag','uipanel1_tag') function, you can easily find the desired handle.

MATLAB GUI tab ordering

In my current project I have a bunch of edit text boxes in my gui. When I/m in the first text blank and hit the tab key it skips to the third text box, when I hit tab again it goes to the second box. Every time I hit tab it jumps around in this weird order. I found out that the order is dependent on the order of the callback function for each text box. Without going in an copy pasting and changing around the code that gets generated by guide is there a better way to order my text boxes.
So for example when I'm in the box red x and hit tab it takes me to the box red z, than red y than green x then green z. I want to be able to click red x and then using just tab step through and fill out the other blocks. Is it at all possible to re-order?
GUIDE-generated GUI
When using GUIDE, you can simply use the "Tab Order Editor". Get to it using the following menu item:
For this simple GUI, with a single button and two text boxes, you would see the following dialog box:
Then set the tab order by moving UI objects up/down.
Programmatic GUI
To set the tab order programatically, you can use uistack to reorder the handles.
For example, to move a uicontrol "up" one in the order:
uistack(hui,'up',1)
To see the order of the handles to all controls in figure hf:
ch = get(hf,'Children')