【问题标题】:How to merge cell in DefaultTableModel/JTable?如何在 DefaultTableModel/JTable 中合并单元格?
【发布时间】:2014-03-18 09:09:06
【问题描述】:

我搜索了很多并得到了这个 Q 的一些答案。但其中许多都提到了给出 404 错误的链接。 我想做这样的表:

java中有什么方法可以解决这个问题吗?

【问题讨论】:

  • 在我的一个项目中,我使用that SpanTable。在另一个我使用来自that SO answer 的组头。试试看。
  • 你应该检查this和/或this
  • @Qui 异常在线程“main”java.lang.StackOverflowError
  • @Qui setColumnIdentifiers(columnNames); 导致问题

标签: java swing jtable tablecellrenderer jtableheader


【解决方案1】:

MultiSpanCellTableExample 演示如何通过创建自定义TableUI 来合并单元格。此示例中似乎存在导致StackOverflowError 的问题,至少在Java 6 中是这样。要解决此问题,请在AttributiveCellTableModel.setDataVector() 中替换:

setColumnIdentifiers(columnNames);

与:

this.columnIdentifiers = columnNames;

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。修复后,示例如下所示:

JIDE 也有现成的解决方案,不幸的是它不是免费的。例如CellSpanTable

【讨论】:

  • 我已经使用 JIDE 多年了。 API 非常丰富,也就是说,如果你负担得起的话。我相信他们可能有学生版。不确定。为 jidesoft 做一个谷歌。
【解决方案2】:

MultiCellSpanTableExample 很好,但是如果你的表有太多列,它有一个小问题可能会成为一个大问题。正如您在tenorsax 给出的example 中看到的那样,显然每个表格列的宽度都有一个额外的像素。这些额外的像素加起来,使得每一列都比上一列位移更多。

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

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

与:

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

我知道没有人问过,但我希望这对某人有所帮助。 :)

【讨论】:

  • 谢谢!在发现问题之前找到解决方案是最好的!
【解决方案3】:

使用自定义 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;
}
}

from oracle doc

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

【讨论】:

    猜你喜欢
    • 2010-10-03
    • 2012-07-20
    • 2012-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-14
    相关资源
    最近更新 更多