I am having trouble creating a JTable with scrollbars. I want a JTable with 2 columns and no visible scrollbars.
If I enlarge one of the columns the scrollbars should become visible and the columns resize.
I followed this answer How to make JTable both AutoResize and horizontall scrollable? and works fine which basically comes down to:
JTable table = new JTable() {
@Override
public boolean getScrollableTracksViewportWidth() {
return getPreferredSize().width < getParent().getWidth();
}
};
table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
However, with this solution I cannot shrink the first column. Only if I enlarge the 2nd column and the scrollbars become visible I can shrink the first one.
The required behavior is that the 2 columns are automatically resizable. Meaning that the 1 column can shrink and afterwards extend without the scrollbars popping up. Only when extending one of the columns, so that the view should extend, the scrollbars should pop up.
A scenario:
Any ideas on fixing this?
An SSCCE:
import javax.swing.JDialog;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.WindowConstants;
import javax.swing.table.AbstractTableModel;
import java.awt.BorderLayout;
import java.awt.Container;
public class TableTest {
public TableTest() {
JDialog mainDialog = new JDialog();
mainDialog.setResizable( true );
mainDialog.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
Container contentPane = mainDialog.getContentPane();
JTable myTable = new JTable() {
@Override
public boolean getScrollableTracksViewportWidth() {
return getPreferredSize().width < getParent().getWidth();
}
};
myTable.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
myTable.setModel( new MyTableModel() );
JScrollPane scrollPane = new JScrollPane( myTable );
contentPane.add( scrollPane, BorderLayout.CENTER );
mainDialog.pack();
mainDialog.setVisible( true );
}
public static void main( String[] args ) {
new TableTest();
}
private class MyTableModel extends AbstractTableModel {
@Override public int getRowCount() {
return 1;
}
@Override public int getColumnCount() {
return 2;
}
@Override public Object getValueAt( int rowIndex, int columnIndex ) {
return "ARandomValue";
}
}
}
setReorderingAllowed() method and set the value as false.
Right-click on the table cells. From popup menu, choose "Table Contents..". Uncheck the editable check box for the column you want to make it non-editable.
The JTable class is a part of Java Swing Package and is generally used to display or edit two-dimensional data that is having both rows and columns. It is similar to a spreadsheet. This arranges data in a tabular form.
It's not quite enough to override the getTracks method, you have to fool super's layout into doing the right-thingy if tracking:
JTable myTable = new JTable(10, 4) {
private boolean inLayout;
@Override
public boolean getScrollableTracksViewportWidth() {
return hasExcessWidth();
}
@Override
public void doLayout() {
if (hasExcessWidth()) {
// fool super
autoResizeMode = AUTO_RESIZE_SUBSEQUENT_COLUMNS;
}
inLayout = true;
super.doLayout();
inLayout = false;
autoResizeMode = AUTO_RESIZE_OFF;
}
protected boolean hasExcessWidth() {
return getPreferredSize().width < getParent().getWidth();
}
@Override
public void columnMarginChanged(ChangeEvent e) {
if (isEditing()) {
// JW: darn - cleanup to terminate editing ...
removeEditor();
}
TableColumn resizingColumn = getTableHeader().getResizingColumn();
// Need to do this here, before the parent's
// layout manager calls getPreferredSize().
if (resizingColumn != null && autoResizeMode == AUTO_RESIZE_OFF
&& !inLayout) {
resizingColumn.setPreferredWidth(resizingColumn.getWidth());
}
resizeAndRepaint();
}
};
Might not be entirely complete (probably still isn't, even after the edit to take care of columnMarginChanged, copied from JXTable (of the SwingX project) which support that behaviour by an additional layout property
xTable.setHorizontalScrollEnabled(true);
With the implementation of @kleopatra, I noticed that you get a scrollbar, when you reduce the size of a column and then increase it again just slightly (which happens quite often by accident). So I've slightly changed the code slightly:
protected boolean hasExcessWidth() {
return getPreferredSize().width - getParent().getWidth() < 50;
}
This allows to slowly increase the size of a column without loosing the auto resize.
Not really sure yet if the magic "50" is a good measurement, but works quite well in initial tests
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With