问题
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:
- Shrink the 1st column -> 2nd one enlarges, no scrollbars
- Enlarge the 1st column -> 2nd one shrinks, still no scrollbars
- Enlarge the 2nd column -> 1 column stays the same, 2nd one enlarges and scrollbars appear
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";
}
}
}
回答1:
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);
回答2:
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
来源:https://stackoverflow.com/questions/15499255/jtable-with-autoresize-horizontal-scrolling-and-shrinkable-first-column