JTable with autoresize, horizontal scrolling and shrinkable first column

僤鯓⒐⒋嵵緔 提交于 2019-12-30 04:58:07

问题


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:

  1. Shrink the 1st column -> 2nd one enlarges, no scrollbars
  2. Enlarge the 1st column -> 2nd one shrinks, still no scrollbars
  3. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!