Uitable over whole window width - matlab

I would like to programmatically (or in GUIDE) fix the matlab-uitable to be the whole width of the panel on initialisation. How can I do this?
All I've managed is to change the size in pixels of single columns. I would like the uitable to be 100% the width of the page at that time. When my window is in minimized form the GUI looks fine, but when I maximize it, the uitable is only about half the width of the page. (The uitable's height is not that of the whole panel though, around 1/2 of the whole page)
The GUI is written in matlab-guide.
This is the code that I am trying right now:
data = populateTable;
parentPosition = get(handles.uipanel4, 'position');
uitablePosition = [x y parentPosition(3)-2 parentPosition(4)-2];
set(handles.uitable, 'Position', uitablePosition);
set(handles.uitable, 'Visible', 'on');
set(handles.uitable, 'Data',data, 'ColumnFormat',{'numeric'});

A possible solution could be to set both the position of the figure and of the table to normalized, then to set the position of the table to [0 0 1 1]
f = figure
set(f,'unit','normalized')
set(f,'position',[0.1 0.1 0.5 0.5])
data = rand(13);
for i=1:length(data)
col_names{i}=['Col. # ' int2str(i)];
end
for i=1:length(data)
row_names{i}=['Row. # ' int2str(i)];
end
t = uitable(f, 'Data', data,'unit','normalized', ...
'Position', [0 0 1 1],'columnname',col_names, ...
'rowname',row_names);

You need to set the uitable's position property when you initialize it.
First, get the position of the uitable's parent object. That could be a uipanel or a figure. Assume hParent is a handle to the uitable's parent.
parentPosition = get(hParent, 'position');
Then, create your position vector for the new uitable, and use the parent's width and height. You might want to subtract a few pixels for padding. I'll subtract two pixels here.
uitablePosition = [x y parentPosition(3)-2 parentPosition (4)-2];
You can probably set x and y to 1 or 2 as well, depending on where the table is positioned.
uitable( ... 'units','pixels','position', uitablePosition )
You can implement the same idea in your figure's resize function.

Related

UI elements sometimes appear in the wrong place

I have the following MATLAB script:
fig = figure('Position', [150 30 900 600]);
%height = 2100; % Works as expected
height = 2400; % Elements appear in the wrong places
panel = uipanel(fig, 'Units', 'pixels', 'Position', [0 0 900 height]);
xs = linspace(-pi,pi,101);
ys = sin(xs);
width = 300;
height = 300;
yOffset = height*19;
for x = 1:3
for y = 1:2
a = axes(panel, 'Units', 'pixels');
a.Position = [(x-1) * width, (y-1) * height, width, height];
plot(a, xs, ys);
end
end
When run, I expect this to create a figure containing a panel and 6 tiled axes that should fill the entire figure window. Instead, the axes elements appear to be shifted up, and partially off, of the panel and figure. This looks like:
If I change height to a lower number, such as 2100, I get what I expect:
Since positions are relative to the bottom left corner, I don't see why changing the height would make the axes elements move like this. It isn't a smooth transition, if the height isn't too high, the axes are in the right place, but once the height is too high, further increases in height cause the axes to move further and further up the window.
I am using MATLAB R2017a. Am I doing something wrong? What is the cause of this?
Note: I am aware that my panel is much bigger than the figure, this is intentional and desired for my application.

MATLAB: The exact size and position of the axis box in the case of `axis equal`?

How to know the exact size and position of the axis box (without axis labels and numbers)? For example, if I use
figure
contourf(x,y,u,100,'linestyle','none')
axis equal
set(gca,'position',[0.1,0.1,0.7,0.8]) %normalized units
The size of the axis frame/box is varyed in the case of the figure window resizing (or using axis equal), but the value of get(gca,'position') remains unchanged. For example:
figure
Z = peaks(20);
contourf(Z,10)
set(gca,'Units','pixels')
get(gca,'position')
axis equal
get(gca,'position')
ans =
0.1300 0.1100 0.7750 0.8150
after axis equal, the axis box is changed, but get(gca,'position') gives the same coordinates:
ans =
0.1300 0.1100 0.7750 0.8150
I need these to align the colorbar to the axis box (with fixed gap between them) in the case of axis equal.
When you call axis equal, the axis box aspect ratio is fixed and the Position property is treated as a maximum size. When you resize the figure window, the axis box will remain centered in the Position rectangle, but in order to maintain the same aspect ratio as before, it may not take up the entire Position rectangle.
If you want it to take up the entire Position rectangle, you can call axis equal again. (this may depend on your MATLAB version; it worked for me in R2015b).
This is also discussed in a bit more detail on MATLAB Central.
To answer your original question, it's a bit complicated. You'd have to get the plot box aspect ratio (using pbaspect() or the axes PlotBoxAspectRatio property) and figure it out:
ah = gca();
% Get the axes Position rectangle in units of pixels
old_units = get(ah,'Units');
set(ah,'Units','pixels');
pos = get(ah,'Position');
set(ah,'Units',old_units);
% Figure the PlotBox and axes Position aspect ratios
pos_aspectRatio = pos(3) / pos(4);
box_aspect = pbaspect(ah);
box_aspectRatio = box_aspect(1) / box_aspect(2);
if (box_aspectRatio > pos_aspectRatio)
% PlotBox is wider than the Position rectangle
box_height = pos(3) / box_aspectRatio;
box_dy = (pos(4)-box_height) / 2;
box_position = [pos(1), pos(2)+box_dy, pos(3), box_height];
else
% PlotBox is taller than the Position rectangle
box_width = pos(4) * box_aspectRatio;
box_dx = (pos(3)-box_width) / 2;
box_position = [pos(1)+box_dx, pos(2), box_width, pos(4)];
end
Note that this will give you the box position in pixels; if you want it in the normalized units that are the axes default, you'll need to normalize it:
fig_pos = get(get(ah,'Parent'),'Position');
box_position = box_position ./ fig_pos([3 4 3 4]);

Simultaneous interaction with 2 figures in MATLAB GUI

I am writing a GUI in MATLAB (guide) where user will be shown 2 images(both images are positioned side by side in single gui window) from a series of images (but each drifted little bit) and will be allowed to select area of interest.
I want user to select working are in image 1 while simultaneously highlighting the selected area in image 2, so that it is easier to judge whether the feature of interest has drifted out of selected area or not. How to do that?
I am using following answer to select and crop area of interest(just FYI):
crop image with fixed x/y ratio
Here is a way to do it using imrect and its addNewPositionCallback method. Check here for a list of available methods.
In the following figure I create 2 axes. On the left that's the original image and on the right that's the "modified" image. By pressing the pushbutton, imrect is called and the addNewPositionCallback method executes a function, called GetROIPosition that is used to get the position of the rectangle defined by imrect. At the same time, in the 2nd axes, a rectangle is drawn with the same position as that in the 1st axes. To be even more fancy you can use the setConstrainedPosition to force the rectangle to be enclosed in a given axes. I'll let you do it :)
Here is the whole code with 2 screenshots:
function SelectROIs(~)
%clc
clear
close all
%//=========================
%// Create GUI components
hfigure = figure('Position',[300 300 900 600],'Units','Pixels');
handles.axesIm1 = axes('Units','Pixels','Position',[30,100,400 400],'XTick',[],'YTIck',[]);
handles.axesIm2 = axes('Units','Pixels','Position',[460,100,400,400],'XTick',[],'YTIck',[]);
handles.TextaxesIm1 = uicontrol('Style','Text','Position',[190 480 110 20],'String','Original image','FontSize',14);
handles.TextaxesIm2 = uicontrol('Style','Text','Position',[620 480 110 20],'String','Modified image','FontSize',14);
%// Create pushbutton and its callback
handles.SelectROIColoring_pushbutton = uicontrol('Style','pushbutton','Position',[380 500 120 30],'String','Select ROI','FontSize',14,'Callback',#(s,e) SelectROIListCallback);
%// ================================
%/ Read image and create 2nd image by taking median filter
handles.Im = imread('coins.png');
[Height,Width,~] = size(handles.Im);
handles.ModifIm = medfilt2(handles.Im,[3 3]);
imshow(handles.Im,'InitialMagnification','fit','parent',handles.axesIm1);
imshow(handles.ModifIm,'InitialMagnification','fit','parent',handles.axesIm2);
guidata(hfigure,handles);
%%
%// Pushbutton's callback. Create a draggable rectangle in the 1st axes and
%a rectangle in the 2nd axes. Using the addNewPositionCallback method of
%imrect, you can get the position in real time and update that of the
%rectangle.
function SelectROIListCallback(~)
hfindROI = findobj(handles.axesIm1,'Type','imrect');
delete(hfindROI);
hROI = imrect(handles.axesIm1,[Width/4 Height/4 Width/2 Height/2]); % Arbitrary size for initial centered ROI.
axes(handles.axesIm2)
rectangle('Position',[Width/4 Height/4 Width/2 Height/2],'EdgeColor','y','LineWidth',2);
id = addNewPositionCallback(hROI,#(s,e) GetROIPosition(hROI));
end
%// Function to fetch current position of the moving rectangle.
function ROIPos = GetROIPosition(hROI)
ROIPos = round(getPosition(hROI));
axes(handles.axesIm2)
hRect = findobj('Type','rectangle');
delete(hRect)
rectangle('Position',ROIPos,'EdgeColor','y','LineWidth',2);
end
end
The figure after pressing the button:
And after moving the rectangle around:
Yay! Hope that helps! Nota that since you're using GUIDE the syntax of the callbacks will look a bit different but the idea is exactly the same.

How to modify uitable cell height (row height) in Matlab?

I have a uitable with 6 row and 6 column and i want to show it in full screen mode for doing this i can change column width but i can't change row height.
Extent is Size of uitable rectangle, but it is read only properties.
With conventional approaches the only possibility to change the row height is by adjusting the 'FontSize' property.
The following function will give you a full-screen table. You can set up 'ColumnWidth' and 'FontSize' until it fills your screen entirely.
function fancyTable
columnwidth = { 1920/2 1920/2 };
FontSize = 135;
h = figure('units','normalized','Position',[0 0 1 1],...
'numbertitle','off','MenuBar','none');
defaultData = rand(5,2);
uitable(h,'Units','normalized','Position',[0 0 1 1],...
'Data', defaultData,...
'ColumnName', [],'RowName',[],...
'ColumnWidth', columnwidth,...
'FontSize', FontSize,...
'ColumnEditable', [false false],...
'ColumnFormat', {'numeric' , 'numeric'});
end
I don't see a simple solution to change the row-height independently from the font size.
But there are some ideas at undocumented Matlab.
"
7. JIDE customizations
... Similarly, this section explains how we can use JIDE to merge together adjacent cells:
"
Could be a fiddly workaround, and there are no code-examples.
You can e.g. use the findjobj utility from the file exchange.
It will get you to the underlying java object of the table, somewhere along the lines of:
t = uitable(...);
scrollPane = findjobj(t);
% not 100% sure about this, but there'll be a `UITablePeer` object somewhere within that scrollPane
jTable = scrollPane.getComponent(0);
This jTable will have a setRowHeight method inherited from http://docs.oracle.com/javase/7/docs/api/javax/swing/JTable.html

Set pixels on screen efficiently

I am using WindowAPI (http://www.mathworks.com/matlabcentral/fileexchange/31437) to show a black full screen in matlab.
When drawing on screen, turns out drawing using line() and rectangle() functions is extremely slow.
How can I set values of pixels without going through matlab's mechanism? Getting the window's canvas for example would be great.
One way to imitate a "canvas" is by using a MATLAB image. The idea is to manually change its pixels and update the 'CData' of the plotted image.
Note that you can use an image with the same dimensions as your screen size (image pixels will correspond to screen pixels one-to-one), but updating it would be slower. The trick is to keep it small and let MATLAB map it to the entire fullscreen. That way the image can be thought of as having "fat" pixels. Of course the resolution of the image is going to affect the size of the marker you draw.
To illustrate, consider the following implementation:
function draw_buffer()
%# paramters (image width/height and the indexed colormap)
IMG_W = 50; %# preferably same aspect ratio as your screen resolution
IMG_H = 32;
CMAP = [0 0 0 ; lines(7)]; %# first color is black background
%# create buffer (image of super-pixels)
%# bigger matrix gives better resolution, but slower to update
%# indexed image is faster to update than truecolor
img = ones(IMG_H,IMG_W);
%# create fullscreen figure
hFig = figure('Menu','none', 'Pointer','crosshair', 'DoubleBuffer','on');
WindowAPI(hFig, 'Position','full');
%# setup axis, and set the colormap
hAx = axes('Color','k', 'XLim',[0 IMG_W]+0.5, 'YLim',[0 IMG_H]+0.5, ...
'Units','normalized', 'Position',[0 0 1 1]);
colormap(hAx, CMAP)
%# display image (pixels are centered around xdata/ydata)
hImg = image('XData',1:IMG_W, 'YData',1:IMG_H, ...
'CData',img, 'CDataMapping','direct');
%# hook-up mouse button-down event
set(hFig, 'WindowButtonDownFcn',#mouseDown)
function mouseDown(o,e)
%# convert point from axes coordinates to image pixel coordinates
p = get(hAx,'CurrentPoint');
x = round(p(1,1)); y = round(p(1,2));
%# random index in colormap
clr = randi([2 size(CMAP,1)]); %# skip first color (black)
%# mark point inside buffer with specified color
img(y,x) = clr;
%# update image
set(hImg, 'CData',img)
drawnow
end
end