java JTable 多个标题行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11665397/
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
JTable Multiple Header Rows
提问by Jonno_FTW
I am using a JTable in my application and wish to have 2 rows for headings, similar to this:
我在我的应用程序中使用 JTable 并希望有 2 行标题,类似于:
Is this even possible or will I have to do something else? If so, what? Using Supertitle-titleA, SuperTitle-titleB will take up too much space and make information redundant.
这甚至是可能的还是我必须做其他事情?如果是这样,是什么?使用 Supertitle-titleA 时,SuperTitle-titleB 会占用过多的空间并使信息变得多余。
回答by Roland Schneider
We had the same requirement in our last project. What I have found is an Implementation for a GroupableTableHeader on java2s.com. However, I have pimped it a bit, although I cannot recall what exactly. Beneath is the implementation of the three classes as how we use them.
我们在上一个项目中也有同样的要求。我发现的是java2s.com 上 GroupableTableHeader的实现。但是,我对它进行了一些拉皮条,尽管我不记得到底是什么。下面是三个类的实现以及我们如何使用它们。
ColumnGroup.java
列组.java
import java.awt.Component;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
/**
* ColumnGroup
*
* @version 1.0 20.10.1998
* @author Nobuo Tamemasa
*/
public class ColumnGroup {
protected TableCellRenderer renderer;
protected List<TableColumn> columns;
protected List<ColumnGroup> groups;
protected String text;
protected int margin = 0;
public ColumnGroup(String text) {
this(text, null);
}
public ColumnGroup(String text, TableCellRenderer renderer) {
this.text = text;
this.renderer = renderer;
this.columns = new ArrayList<TableColumn>();
this.groups = new ArrayList<ColumnGroup>();
}
public void add(TableColumn column) {
columns.add(column);
}
public void add(ColumnGroup group) {
groups.add(group);
}
/**
* @param column
* TableColumn
*/
public List<ColumnGroup> getColumnGroups(TableColumn column) {
if (!contains(column)) {
return Collections.emptyList();
}
List<ColumnGroup> result = new ArrayList<ColumnGroup>();
result.add(this);
if (columns.contains(column)) {
return result;
}
for (ColumnGroup columnGroup : groups) {
result.addAll(columnGroup.getColumnGroups(column));
}
return result;
}
private boolean contains(TableColumn column) {
if (columns.contains(column)) {
return true;
}
for (ColumnGroup group : groups) {
if (group.contains(column)) {
return true;
}
}
return false;
}
public TableCellRenderer getHeaderRenderer() {
return renderer;
}
public void setHeaderRenderer(TableCellRenderer renderer) {
this.renderer = renderer;
}
public String getHeaderValue() {
return text;
}
public Dimension getSize(JTable table) {
TableCellRenderer renderer = this.renderer;
if (renderer == null) {
renderer = table.getTableHeader().getDefaultRenderer();
}
Component comp = renderer.getTableCellRendererComponent(table, getHeaderValue() == null || getHeaderValue().trim().isEmpty() ? " "
: getHeaderValue(), false, false, -1, -1);
int height = comp.getPreferredSize().height;
int width = 0;
for (ColumnGroup columnGroup : groups) {
width += columnGroup.getSize(table).width;
}
for (TableColumn tableColumn : columns) {
width += tableColumn.getWidth();
width += margin;
}
return new Dimension(width, height);
}
public void setColumnMargin(int margin) {
this.margin = margin;
for (ColumnGroup columnGroup : groups) {
columnGroup.setColumnMargin(margin);
}
}
}
GroupableTableHeader.java
GroupableTableHeader.java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
* GroupableTableHeader
*
* @version 1.0 20.10.1998
* @author Nobuo Tamemasa
*/
@SuppressWarnings("serial")
public class GroupableTableHeader extends JTableHeader {
@SuppressWarnings("unused")
private static final String uiClassID = "GroupableTableHeaderUI";
protected List<ColumnGroup> columnGroups = new ArrayList<ColumnGroup>();
public GroupableTableHeader(TableColumnModel model) {
super(model);
setUI(new GroupableTableHeaderUI());
setReorderingAllowed(false);
// setDefaultRenderer(new MultiLineHeaderRenderer());
}
@Override
public void updateUI() {
setUI(new GroupableTableHeaderUI());
}
@Override
public void setReorderingAllowed(boolean b) {
super.setReorderingAllowed(false);
}
public void addColumnGroup(ColumnGroup g) {
columnGroups.add(g);
}
public List<ColumnGroup> getColumnGroups(TableColumn col) {
for (ColumnGroup group : columnGroups) {
List<ColumnGroup> groups = group.getColumnGroups(col);
if (!groups.isEmpty()) {
return groups;
}
}
return Collections.emptyList();
}
public void setColumnMargin() {
int columnMargin = getColumnModel().getColumnMargin();
for (ColumnGroup group : columnGroups) {
group.setColumnMargin(columnMargin);
}
}
}
GroupableTableHeaderUI.java
GroupableTableHeaderUI.java
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicTableHeaderUI;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class GroupableTableHeaderUI extends BasicTableHeaderUI {
protected GroupableTableHeader getHeader() {
return (GroupableTableHeader) header;
}
@Override
public void paint(Graphics g, JComponent c) {
Rectangle clipBounds = g.getClipBounds();
if (header.getColumnModel().getColumnCount() == 0) {
return;
}
int column = 0;
Dimension size = header.getSize();
Rectangle cellRect = new Rectangle(0, 0, size.width, size.height);
Map<ColumnGroup, Rectangle> groupSizeMap = new HashMap<ColumnGroup, Rectangle>();
for (Enumeration<TableColumn> enumeration = header.getColumnModel().getColumns(); enumeration.hasMoreElements();) {
cellRect.height = size.height;
cellRect.y = 0;
TableColumn aColumn = enumeration.nextElement();
List<ColumnGroup> groups = getHeader().getColumnGroups(aColumn);
int groupHeight = 0;
for (ColumnGroup group : groups) {
Rectangle groupRect = groupSizeMap.get(group);
if (groupRect == null) {
groupRect = new Rectangle(cellRect);
Dimension d = group.getSize(header.getTable());
groupRect.width = d.width;
groupRect.height = d.height;
groupSizeMap.put(group, groupRect);
}
paintCell(g, groupRect, group);
groupHeight += groupRect.height;
cellRect.height = size.height - groupHeight;
cellRect.y = groupHeight;
}
cellRect.width = aColumn.getWidth();
if (cellRect.intersects(clipBounds)) {
paintCell(g, cellRect, column);
}
cellRect.x += cellRect.width;
column++;
}
}
private void paintCell(Graphics g, Rectangle cellRect, int columnIndex) {
TableColumn aColumn = header.getColumnModel().getColumn(columnIndex);
TableCellRenderer renderer = aColumn.getHeaderRenderer();
if (renderer == null) {
renderer = getHeader().getDefaultRenderer();
}
Component c = renderer.getTableCellRendererComponent(header.getTable(), aColumn.getHeaderValue(), false, false,
-1, columnIndex);
c.setBackground(UIManager.getColor("control"));
rendererPane.paintComponent(g, c, header, cellRect.x, cellRect.y, cellRect.width, cellRect.height, true);
}
private void paintCell(Graphics g, Rectangle cellRect, ColumnGroup cGroup) {
TableCellRenderer renderer = cGroup.getHeaderRenderer();
if (renderer == null) {
renderer = getHeader().getDefaultRenderer();
}
Component component = renderer.getTableCellRendererComponent(header.getTable(), cGroup.getHeaderValue(), false,
false, -1, -1);
rendererPane
.paintComponent(g, component, header, cellRect.x, cellRect.y, cellRect.width, cellRect.height, true);
}
private int getHeaderHeight() {
int headerHeight = 0;
TableColumnModel columnModel = header.getColumnModel();
for (int column = 0; column < columnModel.getColumnCount(); column++) {
TableColumn aColumn = columnModel.getColumn(column);
TableCellRenderer renderer = aColumn.getHeaderRenderer();
if (renderer == null) {
renderer = getHeader().getDefaultRenderer();
}
Component comp = renderer.getTableCellRendererComponent(header.getTable(), aColumn.getHeaderValue(), false,
false, -1, column);
int cHeight = comp.getPreferredSize().height;
List<ColumnGroup> groups = getHeader().getColumnGroups(aColumn);
for (ColumnGroup group : groups) {
cHeight += group.getSize(header.getTable()).height;
}
headerHeight = Math.max(headerHeight, cHeight);
}
return headerHeight;
}
@Override
public Dimension getPreferredSize(JComponent c) {
int width = 0;
for (Enumeration<TableColumn> enumeration = header.getColumnModel().getColumns(); enumeration.hasMoreElements();) {
TableColumn aColumn = enumeration.nextElement();
width += aColumn.getPreferredWidth();
}
return createHeaderSize(width);
}
private Dimension createHeaderSize(int width) {
TableColumnModel columnModel = header.getColumnModel();
width += columnModel.getColumnMargin() * columnModel.getColumnCount();
if (width > Integer.MAX_VALUE) {
width = Integer.MAX_VALUE;
}
return new Dimension(width, getHeaderHeight());
}
}
回答by MadProgrammer
Yes, you need to supply your own JTableHeader. The difficult comes in trying to layout it out.
是的,您需要提供自己的JTableHeader。困难在于尝试对其进行布局。
You'll need to look at JTableHeader.getHeaderRect(column), this tells the renderer how to layout the column headers.
您需要查看JTableHeader.getHeaderRect(column),它告诉渲染器如何布局列标题。
You're going to have to take into consideration the height of each column renderer as well as the height of the component you want to use a label renderer (I'd suggest using the Header's column renderer as a bases, but that's up to you)
您将不得不考虑每个列渲染器的高度以及要使用标签渲染器的组件的高度(我建议使用 Header 的列渲染器作为基础,但这取决于您)
回答by Anzhi
Take account of space between columns (when more then two columns join to group - right border of group column become invisible). Here is solution:
考虑列之间的空间(当多于两列加入组时 - 组列的右边框变得不可见)。这是解决方案:
public Dimension getSize(JTable table) {
Component comp = renderer.getTableCellRendererComponent(
table, getHeaderValue(), false, false,-1, -1);
int height = comp.getPreferredSize().height;
int width = 0;
Enumeration e = v.elements();
int testNum = 0;
while (e.hasMoreElements()) {
Object obj = e.nextElement();
if (obj instanceof TableColumn) {
TableColumn aColumn = (TableColumn)obj;
width += aColumn.getWidth()-table.getIntercellSpacing().width;
width += margin;
} else {
width += ((ColumnGroup)obj).getSize(table).width-table.getIntercellSpacing().width;
}
}
return new Dimension(width+2*table.getIntercellSpacing().width, height);
}