JTable具有自动调整大小,水平滚动和可收缩的第一列

时间:2013-03-19 12:15:40

标签: java swing jtable jscrollpane

我在使用滚动条创建JTable时遇到问题。 我想要一个带有2列且没有可见滚动条的JTable。

如果我放大其中一列,滚动条应该变为可见,列会调整大小。

我遵循了这个答案How to make JTable both AutoResize and horizontall scrollable?并且工作正常,基本上归结为:

JTable table = new JTable() {
  @Override
  public boolean getScrollableTracksViewportWidth() {
    return getPreferredSize().width < getParent().getWidth();
  }
};
table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );

但是,使用此解决方案,我无法收缩第一列。只有当我放大第二列并且滚动条变得可见时,我才能缩小第一列。

所需的行为是2列可自动调整大小。这意味着1列可以缩小,然后在没有滚动条弹出的情况下延伸。只有在扩展其中一列时,才能使视图延伸,弹出滚动条。

场景:

  1. 收缩第1列 - &gt;第二个放大,没有滚动条
  2. 放大第1列 - &gt;第二个收缩,仍然没有滚动条
  3. 放大第二列 - &gt; 1列保持不变,第2列放大,滚动条出现
  4. 有关解决这个问题的任何想法吗?

    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";
    }
    }
    }
    

2 个答案:

答案 0 :(得分:6)

覆盖getTracks方法还不够,如果跟踪,你必须愚弄超级布局做正确的事情:

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();
    }

};

可能还没有完全完成(可能仍然不是,即使在编辑之后,要处理columnMarginChanged,从JXTable(SwingX project)复制,通过其他布局属性支持该行为

xTable.setHorizontalScrollEnabled(true);

答案 1 :(得分:1)

随着@kleopatra的实现,我注意到你得到一个滚动条,当你减小一个列的大小然后再稍微增加它(这经常发生意外)。所以我略微改变了代码:

protected boolean hasExcessWidth() {
    return getPreferredSize().width - getParent().getWidth() < 50;
}

这允许缓慢增加列的大小而不会丢失自动调整大小。

尚不确定神奇的“50”是否是一个很好的测量,但在初始测试中效果很好