如何在DefaultTableModel/JTable中合并单元格?

13

我搜索了很多并得到了一些关于这个问题的答案,但其中许多都引用了404错误的链接。

我想要制作这样的表格:

单元格合并数目不固定

在Java中有没有相应的方法可以实现?


在我的一个项目中,我使用了这个SpanTable。在另一个项目中,我使用了这个SO答案中的组标题。你可以试试看。 - alex2410
你应该查看这个和/或这个 - Qiu
@Qui 在主线程中发生异常:java.lang.StackOverflowError。 - Nikhil Chilwant
@Qui setColumnIdentifiers(columnNames); 出现了问题。 - Nikhil Chilwant
3个回答

18

MultiSpanCellTableExample演示了如何通过创建自定义TableUI来合并单元格。这个例子似乎存在问题,至少在Java 6中会导致StackOverflowError。为了解决这个问题,在AttributiveCellTableModel.setDataVector()中,请将以下内容替换:

setColumnIdentifiers(columnNames);

随着:

this.columnIdentifiers = columnNames;

IE:

IE:
public void setDataVector(Vector newData, Vector columnNames) {
    if (newData == null)
        throw new IllegalArgumentException(
                "setDataVector() - Null parameter");
    dataVector = new Vector(0);
    // setColumnIdentifiers(columnNames);
    this.columnIdentifiers = columnNames;
    dataVector = newData;

    cellAtt = new DefaultCellAttribute(dataVector.size(),
            columnIdentifiers.size());

    newRowsAdded(new TableModelEvent(this, 0, getRowCount() - 1,
            TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
问题在于setColumnIdentifiers调用setDataVector,从而触发了StackOverflowError。修复后,示例看起来像这样: enter image description here 还有一个来自JIDE的现成解决方案,但不幸的是它不免费。这里举例说明CellSpanTableenter image description here

1
我已经使用JIDE好几年了。API非常丰富,但是价格也相对较高。我相信他们可能有学生版本,但不确定。可以在谷歌上搜索jidesoft。 - D-Klotz

11

MultiCellSpanTableExample很好,但是如果您的表格有太多列,它会出现一个小问题,这个小问题可能会变成一个巨大的问题。正如您在示例中所看到的,每个表格列的宽度似乎都多了一个像素。这些额外的像素加起来,使每一列比上一列更加偏移。

我可以通过替换以下行来简单地解决这个问题:

cellFrame.width = aColumn.getWidth() + columnMargin;

使用:

cellFrame.width = aColumn.getWidth() + columnMargin - 1;

虽然没有人问,但我希望这能帮到某些人。:)


提前发现问题并找到解决方法是最好的! - xeruf

0
使用自定义的TableCellRenderer。
import java.awt.Color;
import java.awt.Component;

import javax.swing.BorderFactory;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;

public class HeaderRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1L;
TableCellRenderer renderer;

public HeaderRenderer(JTable table) {
  renderer = table.getTableHeader().getDefaultRenderer();
}

@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {

super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
switch (col) {
case 0:
  setBorder(BorderFactory.createMatteBorder(1, 1, 1, 0, Color.LIGHT_GRAY));
break;
case 1:
  setBorder(BorderFactory.createMatteBorder(1, 0, 1, 1, Color.LIGHT_GRAY));
break;
default:
  setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.LIGHT_GRAY));
break;
}
  return this;
}
}

来自Oracle文档

import java.awt.Dimension;
import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;

public class SimpleTableDemo extends JPanel {
private static final long serialVersionUID = 1L;
public SimpleTableDemo() {
super(new GridLayout(1, 0));

String[] columnNames = { "First Name", "Last Name", "Sport", "# of Years", "Vegetarian" };

    Object[][] data = { { "Kathy", "Smith", "Snowboarding", new Integer(5), new Boolean(false) },{ "John", "Doe", "Rowing", new Integer(3), new Boolean(true) },{ "Sue", "Black", "Knitting", new Integer(2), new Boolean(false) },{ "Jane", "White", "Speed reading", new Integer(20), new Boolean(true) },    { "Joe", "Brown", "Pool", new Integer(10), new Boolean(false) } };

JTable table = new JTable(data, columnNames);
TableCellRenderer myRenderer = new HeaderRenderer(table);
table.getTableHeader().setDefaultRenderer(myRenderer);
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);

JScrollPane scrollPane = new JScrollPane(table);

add(scrollPane);
}

private static void createAndShowGUI() {
JFrame frame = new JFrame("SimpleTableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

SimpleTableDemo newContentPane = new SimpleTableDemo();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);

frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接