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

Posted

技术标签:

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

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

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

【问题讨论】:

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

MultiSpanCellTableExample 演示如何通过创建自定义TableUI 来合并单元格。此示例中似乎存在导致***Error 的问题,至少在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 从而触发***Error。修复后,示例如下所示:

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

);


【讨论】:

以上是关于如何在 DefaultTableModel/JTable 中合并单元格?的主要内容,如果未能解决你的问题,请参考以下文章

如何在表单提交后保留文本(如何在提交后不删除自身?)

如何在异步任务中调用意图?或者如何在 onPostExecute 中开始新的活动?

在 Avkit 中如何使用这三行代码,以及如何将音乐静音”

如何在 JDBC 中启动事务?

如何在 Fragment 中调用 OnActivityResult 以及它是如何工作的?

如何使用 Firebase 在 Web 上托管 Flutter?它的效果如何?