1

I'm updating my generic data manipulation GUI and I thought I would make use of a uitable instead of a uicontrol listbox to display the path(s) and filename(s) of the loaded files. I noticed the column headers are centered by default, and I can't seem to figure out how to left align them if the filename is longer than the width of the table. I checked the properties returned by get and poked around with findjobj but didn't find anything obvious. My attempt to use an html string was also unsuccessful.

Am I missing something obvious?

Sample code:

function testcode
res = get(0,'ScreenSize');
figdim = [1280 720]; % Main figure size, pixels
handles.mainfig = figure( ...
    'Units', 'Pixels', ...
    'Position', [(res(3) - figdim(1))/2 (res(4) - figdim(2))/2 figdim(1) figdim(2)], ...
    'Name', 'Meep', ...
    'Resize', 'off', ...
    'DockControls', 'off', ...
    'NumberTitle', 'off', ...
    'Toolbar', 'figure' ...
    );
handles.filetable = uitable( ...
    'Parent', handles.mainfig, ...
    'Units', 'normalized', ...
    'Position', [0.038 0.71 0.235 0.1], ...
    'ColumnName', 'File Loaded', ...
    'Data', {'None'} ...
    );
handles.loadfilebtn = uicontrol( ...
    'Parent', handles.mainfig, ...
    'Style', 'pushbutton', ...
    'Units', 'normalized', ...
    'Position', [0.075 0.85 0.16 0.07], ...
    'String', 'This is a Button, Click', ...
    'Callback', {@abutton} ...
    );
guidata(handles.mainfig, handles);
end
function abutton(hObject,~)
handles = guidata(hObject);

filepath = 'C:\folder\folder\folder\folder\folder\folder\folder\folder\folder\superduperreallylongfilename.fileextension';
set(handles.filetable,'Data',{filepath});
set(handles.filetable,'ColumnWidth',{length(filepath)*5});

test = '<html><left />File Loaded</html>';
set(handles.filetable,'ColumnName',test); % Attempt #1, doesn't work
end
Robert Seifert
  • 25,078
  • 11
  • 68
  • 113
sco1
  • 12,154
  • 5
  • 26
  • 48

2 Answers2

2

The easiest workaround I could think of, is to split table and table-header in two separate uitables. It's a little fiddly to set the position vectors properly, but generally it works like a charm. Important: place the "header-uitable" below (in code first) the "data-table". You save some trouble this way.

function testcode
close all
res = get(0,'ScreenSize');
figdim = [1280 720]; % Main figure size, pixels
handles.mainfig = figure( ...
    'Units', 'Pixels', ...
    'Position', [(res(3) - figdim(1))/2 (res(4) - figdim(2))/2 figdim(1) figdim(2)], ...
    'Name', 'Meep', ...
    'Resize', 'off', ...
    'DockControls', 'off', ...
    'NumberTitle', 'off', ...
    'Toolbar', 'figure' ...
    );
handles.tableheader = uitable( ...
    'Parent', handles.mainfig, ...
    'Units', 'normalized', ...
    'Position', [0.038 0.71 0.235 0.1], ...
    'ColumnName', 'File Loaded', ...
    'ColumnWidth', {271} ...
    );
handles.filetable = uitable( ...
    'Parent', handles.mainfig, ...
    'Units', 'normalized', ...
    'Position', [0.038 0.682 0.235 0.1], ...
    'ColumnName', {}, ...
    'Data', {'None'} ...
    );
handles.loadfilebtn = uicontrol( ...
    'Parent', handles.mainfig, ...
    'Style', 'pushbutton', ...
    'Units', 'normalized', ...
    'Position', [0.075 0.85 0.16 0.07], ...
    'String', 'This is a Button, Click', ...
    'Callback', {@abutton} ...
    );
guidata(handles.mainfig, handles);
end
function abutton(hObject,~)
handles = guidata(hObject);

filepath = 'C:\folder\folder\folder\folder\folder\folder\folder\folder\folder\superduperreallylongfilename.fileextension';
set(handles.filetable,'Data',{filepath});
set(handles.filetable,'ColumnWidth',{length(filepath)*5});

end

enter image description here

Robert Seifert
  • 25,078
  • 11
  • 68
  • 113
2

You've mentioned findjobj, which allows you to get the JTable object behind your table. What you're actually trying to do is change some properties of the header, or JTableHeader object. Once you know what you're looking for the solution is easy to find (e.g. this previous thread).

In summary, put this code at the end of the button callback:

function abutton(hObject,~)
%// ....

hTable = handles.filetable;
jScrollpane = findjobj(hTable);
jTable = jScrollpane.getComponent(0).getComponent(0);
%// You can see the list of components using findjobj(hTable).list
%// Part1:
dtcr = javaObject('javax.swing.table.DefaultTableCellRenderer');
dtcr.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
jTable.getColumn(jTable.getColumnName(0)).setHeaderRenderer(dtcr);
%// Part2:
jRenderer = jTable.getTableHeader().getDefaultRenderer();
jRenderer.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
%// Finalization:
jTable.invalidate();

end

Clicking the button then results in:

...the desired result

Several notes:

  1. Here's the documentation of SwingConstants.
  2. The two Parts are supposed to be two different solutions, but I noticed that it only works if both are present (I have no explanation for this).
  3. I tried setting this in the figure creation function, but that didn't work (I have no explanation for this either).
  4. Tested on MATLAB 2014a.
Community
  • 1
  • 1
Dev-iL
  • 23,742
  • 7
  • 57
  • 99
  • Though I like this java approach, this solution has a major drawback: if you scroll to the right the header disappears. – Robert Seifert Sep 09 '14 at 18:24
  • 1
    I wish I could accept both answers. Utilizing the existing object is what I was hoping to find but @thewaywewalk brings up a good point. The primary motivation for this is to make the interface more visually appealing and the other answer, while pretty hack-ey, better accomplishes the goal. Thank you both :) – sco1 Sep 09 '14 at 18:35
  • @thewaywewalk - I agree with you. This is what I understood that the OP wanted (hopefully, after considering the possible alternatives and drawbacks). – Dev-iL Sep 09 '14 at 19:37