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

9 views (last 30 days)
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};
end
end
both had the same effect.
I searched through other answers and found a way to control the scroll bar here: https://www.mathworks.com/matlabcentral/answers/166939-table-scroll-position-update-problem
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);
drawnow
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: https://www.mathworks.com/matlabcentral/answers/339886-editing-uitable-column-widths-with-cursor-does-not-update-columnwidth-property
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
end
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).
  2 Comments
Paul Maurer
Paul Maurer on 27 Aug 2018
This is not perfect, but it is a huge improvement over previous behavior. It does involve calculating a row from the scroll bar position, but that can be done without too much effort.
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.

More Answers (1)

Song Decn
Song Decn on 17 Feb 2018
I also need an answer for this !!

Categories

Find more on Migrate GUIDE Apps in Help Center and File Exchange

Products

Community Treasure Hunt

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

Start Hunting!