【问题标题】:JTable with autoresize, horizontal scrolling and shrinkable first column具有自动调整大小、水平滚动和可收缩第一列的 JTable
【发布时间】:2013-03-08 02:43:28
【问题描述】:

我在创建带有滚动条的 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. 缩小第一列 -> 第二列放大,没有滚动条
  2. 放大第一列 -> 第二列缩小,仍然没有滚动条
  3. 放大第 2 列 -> 1 列保持不变,第 2 列放大并出现滚动条

有解决这个问题的想法吗?

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

【问题讨论】:

  • 覆盖 scrollableTracksViewportWidth 不应该对列的可调整性有任何影响。您的任何代码是否在操作第一个 TableColumn 的 minWidth、maxWidth 或 resizable 属性?
  • 不,没有代码可以操纵它。有一个 AbstractTableModel 需要一个值列表来填充表。此外,表格被包裹在一个 JScrollPane 中,就是这样。
  • 如需尽快获得更好的帮助,请发帖SSCCE
  • 看到你的编辑:在 JXTable 中不支持 - 当缩小第一列时,其他列被扩展,将它们缩小到初始大小将需要额外的逻辑(不确定这会有多困难,调整大小逻辑在很大程度上是一个黑盒子)

标签: java swing jtable jscrollpane


【解决方案1】:

重写 getTracks 方法是不够的,你必须欺骗 super 的布局来做正确的事情 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();
    }

};

可能不完全完整(可能仍然不完整,即使在编辑处理 columnMarginChanged 之后,从 JXTable(SwingX project)复制,它通过额外的布局属性支持该行为

xTable.setHorizontalScrollEnabled(true);

【讨论】:

  • 看起来很棒!!第一列能够正确收缩。如果我在缩小第一列后放大第一列,是否可以再次缩小第二列?现在,秒列的调整大小的宽度仍然存在。除非我专门放大它,否则它应该会再次自动调整大小。还是 JXTable 是实现这种行为的方法?
  • +1 ..我昨天试图解决这个问题..但无法弄清楚。
  • @user2186247 抱歉,不明白你到底想达到什么目的,所以不能说我是否在 JXTable 中实现了它:-) 无论如何,最好用解释来编辑你的问题或者甚至可以发布一个新的(原来的问题已经解决了,不是吗?)
  • Any idea if it would be possible to shrink the seconds column。将调整大小模式更改为 ALL 而不是 SUBSEQUENT
  • 在原始问题中,OP 只有两列。当没有水平滚动条时,您不能缩小第二列,因为 SUBSEQUENT 没有地方分配额外的空间。当您使用 ALL 时,第一列会随着第二列的缩小而增加。
【解决方案2】:

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

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

这允许在不丢失自动调整大小的情况下缓慢增加列的大小。

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

【讨论】:

    猜你喜欢
    • 2011-08-31
    • 1970-01-01
    • 2012-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-10
    相关资源
    最近更新 更多