How to update uitable data without resetting column widths and scroll position?

22 views (last 30 days)
Paul Maurer
Paul Maurer on 26 Jan 2018
Commented: Kevin Phung on 20 Feb 2019
I am writing a gui that monitors instrument data. Some of the data updates every 4.5 seconds. Other data is received every 10 ms or 50 ms. I am slowing the table updates down to about to a few times per second so the values are visible. All of that is working fine.
The issue that I am having is that every time I update the uitable data, the column widths are reset to the their original values and the scroll position resets back to top. This is annoying on the 4.5 second data and unusable on the faster data.
I update the data with:
set(handles.myuitable, 'Data', out);
where handles.myuitable is a handle to the uitable and out is a cell array of the data I want. out is always a fixed size. The contents change, but not the dimensions. I also tried:
handles.myuitable.Data = out
and a for loop:
for ii=1:size(out, 1)
for jj=1:size(out, 2)
handles.myuitable.Data{ii,jj} = out{ii,jj};
both had the same effect.
I searched through other answers and found a way to control the scroll bar here:
I adapted the code as:
jScrollpane = findjobj(handles.myuitable); % get the handle of the table
scroll = jScrollpane.getVerticalScrollBar.getValue; % get the current position of the scroll
set(handles.myuitable, 'Data', out);
jScrollpane.getVerticalScrollBar.setValue(scroll); % set scroll position to the end
With this code, every update causes the scroll bar to jump up to the top and jump back down to the previous position. The table data sometimes experiences a draw error and the table needs to be manually scrolled up and and then down to fix the issue. So this really isn't an improvement.
For the column width, I found a partial solution here:
The adapted code is:
jTable = findjobj(handles.myuitable); % Get the java container
colCount = jTable.getViewport.getView.getColumnModel.getColumnCount(); % Get column count
colWidth = cell(1,colCount); % Instantiate cell array that will contain the column width (pixels) of each column
for idx = 0:(colCount-1)
colWidth{idx+1} = jTable.getViewport.getView.getColumnModel.getColumn(idx).getWidth(); % Dig deep, DEEP into the java container
set(handles.criticaltelem, 'ColumnWidth', colWidth);
<<Scroll bar code from above>>
This saves the column widths before the data is updated so they "reset" to their current value. I say it is a partial solution because if the user is in the process of resizing the columns when the data is updated all columns reset to 75 pixels regardless of any previous settings. Note that my original widths set in GUIDE are [300, 150, 150, 150], so the 75 px numbers do NOT come from my code. This is annoying on the 4.5 second updates. The user can time resizing operations to be between updates. It is unusable on the faster data. So, again, not much of an improvement.
Is there a way to update the uitable data without triggering these unnecessary scroll and column width resets? Should I be using something other than uitable? The user never edits the data, but I like the presentation of the uitable. I would be willing to switch to something with similar presentation. I have about 75 rows (varies between the different tables) and 4 columns. We have access to a fairly large variety of toolboxes, if that helps, but I do have a requirement to make this a stand alone application with application compiler, so the solution has to be compatible with that toolbox.

Accepted Answer

Can Yuce
Can Yuce on 24 Aug 2018
If you want the scroll bar not to jump up to the top and jump back down to the previous position, you can use the following workaround. You can programmatically select a new row, then the focus is switched to the view making the selected row now visible again.The working solution running safely on Java Swing’s Event Dispatch Thread (EDT) without risking a race-condition or deadlock with the EDT would be:
jscrollpane = javaObjectEDT(findjobj(src));
viewport = javaObjectEDT(jscrollpane.getViewport);
jtable = javaObjectEDT( viewport.getView );
jtable.scrollRowToVisible(row_ - 1);
It requires findjobj functionality, and works fine on Matlab R2017a. Other solutions exists but may risk race-conditions with the Event Dispatch Thread (EDT).
Kevin Phung
Kevin Phung on 20 Feb 2019
can you elaborate on the improvement?
right after I change the data in my uitable, it still jumps back to the top scroll position before jumping back down to its previous position.

Sign in to comment.



Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!