Java 如何合并 DefaultTableModel/JTable 中的单元格?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21856733/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to merge cell in DefaultTableModel/JTable?
提问by Nikhil Chilwant
I searched a lot and got some answers for this Q. but many of them referred to links which give 404 error. I want to make table like this:
我搜索了很多,得到了一些关于这个问题的答案。但其中很多都提到了给出 404 错误的链接。我想制作这样的表格:
Is there any method in java for this?
java中有什么方法可以解决这个问题吗?
采纳答案by tenorsax
MultiSpanCellTableExampledemonstrates how to merge cells by creating a custom TableUI
. There seem to be a problem in this example that causes StackOverflowError
, at least in Java 6. To fix this, inside AttributiveCellTableModel.setDataVector()
replace:
MultiSpanCellTableExample演示了如何通过创建自定义TableUI
. 在这个例子中似乎有一个问题导致StackOverflowError
,至少在 Java 6 中。要解决这个问题,请在内部AttributiveCellTableModel.setDataVector()
替换:
setColumnIdentifiers(columnNames);
with:
和:
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));
}
The problem is that setColumnIdentifiers
calls into setDataVector
hence triggering the StackOverflowError
. Once fixed, this is how the example looks like:
问题是setColumnIdentifiers
调用 intosetDataVector
从而触发了StackOverflowError
. 修复后,示例如下所示:
There is also a ready solution from JIDE, unfortunately it is not free. Here is for example CellSpanTable
:
JIDE也有现成的解决方案,不幸的是它不是免费的。例如CellSpanTable
:
回答by Pedro Lima
MultiCellSpanTableExampleis fine, but it has a little problem that can become a huge problem if your table has too many columns. As you can see in the examplegiven by tenorsax, apparently each table column has an extra pixel in their width. Those additional pixels add up, making each column more displaced than the last.
MultiCellSpanTableExample很好,但它有一个小问题,如果您的表有太多列,它可能会成为一个大问题。正如您在Tenorsax 给出的示例中所见,显然每个表格列的宽度都有一个额外的像素。这些额外的像素加起来,使每一列比上一列移位更多。
I could simply fix that by replacing the line:
我可以通过替换该行来简单地解决这个问题:
cellFrame.width = aColumn.getWidth() + columnMargin;
with:
和:
cellFrame.width = aColumn.getWidth() + columnMargin - 1;
I know nobody asked, but I hope this helps someone. :)
我知道没有人问过,但我希望这对某人有所帮助。:)
回答by Friedolin
Use a custom TableCellRenderer
使用自定义 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;
}
}
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();
}
});
}
}