📄 plotdata.m
字号:
% Create the tab pane
tp = awtcreate('javax.swing.JTabbedPane');
[jh,hContainer] = javacomponent(tp, [2,0,hFigPos(3:4)], hFig); %#ok - jh is unused
set(hContainer,'units','normalized', 'tag','jTabbedPane', 'userdata',tp, 'visible','on');
set(hFig, 'userdata',tp);
sp = schema.prop(handle(tp),'UserData','mxArray'); %#ok - sp is unused
userdata = struct('container',hContainer, 'tables',handle([]), 'scroll',handle([]));
set(tp, 'userdata',userdata);
hActiveX = tp; % return tabbedPane to caller
tp.setTabPlacement(tp.BOTTOM);
end % If found a relevant ActiveX
%end % if worksheet object does not yet exist
%% Set the data within the spreadsheet according to supplied axis
function setWorksheetAxisData(acx, ax, axIdx)
% Set the worksheet name according to the axis title (remove all invalid chars)
sheetName = regexprep(get(get(ax,'title'),'string'), '[\\{}]', '');
if isempty(sheetName)
sheetName = get(ancestor(ax,'figure'),'name');
end
if isempty(sheetName)
%sheetName = 'Plot data';
sheetName = ['Axis #' num2str(axIdx)];
end
% Loop over all axes plot lines
% TODO: handle non-'type'='line' datum (annotations etc.)
%hLines = findall(ax,'type','line');
%hLines = sort(findall(ax,'-not','type','axes','-not','type','text'));
hLines = sort(get(ax,'child'));
numLines = length(hLines);
if (numLines == 0)
return; % no data lines - skip this worksheet
end
validIdx = 1;
for lineIdx = 1 : numLines
hLine = hLines(lineIdx);
newXData = get(hLine,'xdata')';
if lineIdx>1 & ~isequal(size(newXData),size(xdata{1})) %#ok ML6
continue; % All data vectors must be the same length
end
xdata{:,validIdx} = newXData; %#ok mlint
ydata{:,validIdx} = get(hLine,'ydata')'; %#ok mlint
seriesName = strrep(get(hLine,'tag'),'\','');
if isempty(seriesName) & isprop(hLine,'DisplayName') %#ok ML6
seriesName = strrep(get(hLine,'DisplayName'),'\','');
end
yHeaders{:,validIdx} = seriesName; %#ok mlint
if isprop(hLine,'color')
color(validIdx) = getBGR(get(hLine,'color')); %#ok
else
color(validIdx) = getBGR([0,0,0]); %#ok mlint
end
validIdx = validIdx + 1;
end
% Get the X-axis name
xAxisNames = get(get(ax,'XLabel'),{'string','userdata'});
xAxisName = regexprep(strcat(xAxisNames{:}), '[\\{}]', '');
% Set the data in the worksheet
setWorksheetData(acx, sheetName, xdata, ydata, xAxisName, yHeaders, color);
%% Freeze pane beneath the headers
function freezePane(acx,cell)
%acx.Range(cell).Select;
selectRange(acx,cell);
iter = 1;
maxIter = 10;
thisWin = acx.ActiveWindow;
thisWin.FreezePanes = 1;
while (iter < maxIter & ~thisWin.FreezePanes) %#ok ML6
pause(0.05);
iter = iter + 1;
thisWin.FreezePanes = 1;
end
%% convert color from Matlab to Microsoft decimal BGR format (a number)
function bgrColor = getBGR(color)
bgrColor = sum(floor(color*255) .* (256.^[0,1,2]));
%% convert color from Microsoft decimal BGR format to HTML hexa RGB format (a string)
function rgbColorStr = getRGB(color)
bgrColorStr = dec2hex(color);
rgbColorStr = bgrColorStr(:,[5,6,3,4,1,2]);
%% Get pixel position of an HG object (replacement for getpixelposition() in ML6)
function pos = getPixelPos(hObj)
try
% getpixelposition is unvectorized unfortunately!
pos = getpixelposition(hObj);
catch
% Matlab 6 did not have getpixelposition nor hgconvertunits so use the old way...
pos = getPos(hObj,'pixels');
end
%% Get position of an HG object in specified units
function pos = getPos(hObj,units)
% Matlab 6 did not have hgconvertunits so use the old way...
oldUnits = get(hObj,'units');
if strcmpi(oldUnits,units) % don't modify units unless we must!
pos = get(hObj,'pos');
else
set(hObj,'units',units);
pos = get(hObj,'pos');
set(hObj,'units',oldUnits);
end
%% Set worksheet data
function setWorksheetData(acx, titleStr, xdata, ydata, xAxisName, yHeaders, color)
% Initialize
if nargin<2, titleStr = 'Plot data'; end
if nargin<3, xdata = []; end
if nargin<4, ydata = []; end
if nargin<5 | isempty(xAxisName), xAxisName = 'X data'; end %#ok ML6
% Args sanity check
if ~ischar(titleStr)
error('Args supplied to plotdata appear to be incorrect - please read help');
end
% Set the worksheet name
sheetName = titleStr;
retryIdx = 0;
renameFlag = 1;
panel = [];
while renameFlag
try
if ~isjava(acx)
set(acx.ActiveSheet,'Name',sheetName);
else
panel = javax.swing.JPanel; % Double-buffered, Flow layout
acx.addTab(sheetName,panel);
end
renameFlag = 0;
catch
% will get here if the sheet name already exists, so we must rename it...
retryIdx = retryIdx + 1;
sheetName = [titleStr ' (' num2str(retryIdx) ')'];
if retryIdx>10 % something large enough but still limited...
rethrow(lasterror);
end
end
end
if (retryIdx>0)
%disp(['Sheet "' titleStr '" already exists - renaming "' sheetName '"']);
end
% Hide gridlines
if ~isjava(acx)
set(acx.ActiveWindow,'DisplayGridlines',0);
set(get(acx.Cells,'Font'), 'Size',8);
else
% TODO
end
% Cell-ize
if ~iscell(xdata) | isscalar(xdata{1}), xdata = {xdata}; end %#ok ML6
if ~iscell(ydata) | isscalar(ydata{1}), ydata = {ydata}; end %#ok ML6
if isempty(xdata) | isempty(xdata{1}) %#ok ML6
%error(['No X data in "' titleStr '"']);
xdata = cellstr(repmat(' ',length(ydata{1}),1));
end
% Set data column-wise
if (size(xdata{1},1) < size(xdata{1},2)) & ~ischar(xdata{1}) & ~iscell(xdata{1}), xdata = {xdata{1}'}; end %#ok ML6
if (size(ydata{1},1) < size(ydata{1},2)) & ~ischar(ydata{1}) & ~iscell(ydata{1}), ydata = {ydata{:}'}; end %#ok ML6
numLines = length(ydata) * size(ydata{1},2);
if (numel(ydata) == 1)
newData = {};
for colIdx = 1 : numLines
newData{colIdx} = ydata{1}(:,colIdx); %#ok mlint
end
ydata = newData;
end
% Default headers = 'Field #...'
if nargin<6, yHeaders = {}; end
if ~iscell(yHeaders), yHeaders = {yHeaders}; end
for fieldIdx = 1 : numLines
if fieldIdx > length(yHeaders) | isempty(yHeaders{fieldIdx}) %#ok ML6
yHeaders{fieldIdx} = ['Field #' num2str(fieldIdx)];
end
end
% Simple processing for Java table...
if isjava(acx)
% Prepare the data table
columnNames = [xAxisName, yHeaders];
userdata = get(acx, 'userdata');
hContainer = userdata.container;
ppos = getPixelPos(hContainer);
tpos = ppos(3:4); %-[4,15];
colWidth = (tpos(1)-55) / length(columnNames);
[ett table] = prepareJTable(columnNames,colWidth,hContainer, [xdata(:,1),ydata]);
% Enable multiple row selection, auto-column resize, and auto-scrollbars
table.setName(sheetName);
table.setPreferredScrollableViewportSize(java.awt.Dimension(tpos(1)-20,16))
table.setSelectionMode(javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
%table.setAutoResizeMode(table.AUTO_RESIZE_SUBSEQUENT_COLUMNS)
sp = com.mathworks.widgets.spreadsheet.SpreadsheetScrollPane(table);
tableSize = java.awt.Dimension(tpos(1)-5,tpos(2)-35);
sp.setPreferredSize(tableSize);
sp.setVerticalScrollBarPolicy(sp.VERTICAL_SCROLLBAR_AS_NEEDED); %_ALWAYS
sp.setHorizontalScrollBarPolicy(sp.HORIZONTAL_SCROLLBAR_AS_NEEDED); %_ALWAYS
%sp.setRowHeader([]); % removes problematic row headers (at left of table)
% Loop over all data fields and set the column colors
if nargin > 6
columns = table.getColumnModel;
color = getRGB(color);
columns.getColumn(0).setHeaderValue(['<html><b>' xAxisName '</b></html>']);
for fieldIdx = 1 : length(yHeaders)
columns.getColumn(fieldIdx).setHeaderValue(['<html><b><font color="#' color(fieldIdx,:) '">' yHeaders{fieldIdx} '</font></b></html>']);
end
end
% Add the table to the tab pane
panel.add(sp);
% Store table & ScrollPane for use in resizing
userdata.tables(end+1) = handle(table);
userdata.scroll(end+1) = handle(sp);
set(acx, 'userdata',userdata);
% Set the focus, to force an immediate repaint
acx.requestFocus;
drawnow;
return;
end
% Default color = Black
if nargin<7
color(1:numLines) = getBGR([0,0,0]); % [0,0,0] = Black
end
%[R,C] = size(data);
C = numLines + 1;
if ischar(xdata{1,1})
R = size(xdata,1);
else
R = length(xdata{1});
end
% Set headers into the spreadsheet
% TODO: handle case of non-aligned x-data (i.e., xdata(:,1)~=xdata(:,2))
%acx.Range(['B1:' nn2an(1,C+1)]).Select;
selection = selectRange(acx,['B1:' nn2an(1,C+1)]);
selection.Value = [xAxisName yHeaders];
set(selection.Font,'Bold',1);
set(selection.Font,'Color',hex2dec('0000FF')); % Red
set(invoke(selection.Border,'Item',4), 'Weight',3);
selection.HorizontalAlignment = -4108; % =xlCenter
% Insert the stats section
statNames = {'min';'max';'average';'median';'stdev';'counta'};
numStats = length(statNames);
setWorksheetStats(acx, C, statNames);
% Set the actual data
% TODO: handle case of non-aligned x-data (i.e., xdata(:,1)~=xdata(:,2))
%data = mat2cell(data, repmat(1,1,R), repmat(1,1,C));
%acx.Range(['B' num2str(2+numStats) ':' nn2an(R+numStats,C+1)]).Value = data;
% X column data:
if ~ischar(xdata{1,1}) & ~iscell(xdata{1,1}) %#ok ML6
xdata = mat2cell(xdata{1}(:,1), repmat(1,1,R), 1);
end
%acx.Range([nn2an(2+numStats,2) ':' nn2an(R+1+numStats,2)]).Value = xdata;
range = selectRange(acx,[nn2an(2+numStats,2) ':' nn2an(R+1+numStats,2)]);
range.Value = xdata;
% Y column(s) data:
if (numLines > 0)
if (size(ydata{1},1) == R)
for lineIdx = 1 : numLines
% Enter the data
data = ydata{:,lineIdx};
if ~iscell(data)
data = mat2cell(data, repmat(1,1,R), 1);
end
% Empty & NaN cells are NOT accepted by XLS ActiveX => 1x0 single...
[data{cellfun('isempty', data)}] = deal(single(zeros(1,0)));
%nanIdx = cellfun(@(x)(~isempty(x) & isnumeric(x) & isnan(x)), data); %#ok ML6 - annonymous funcs invalid in ML6
nanIdx = [];
for cellIdx = length(data) : -1 : 1
x = data{cellIdx};
nanIdx(cellIdx) = ~isempty(x) & isnumeric(x) & isnan(x); %#ok mlint
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -