在jtable渲染表头时,由于有些表头字体较多,需要折行显示,但jtable没有自动折行的功能,所以自己实现表头的渲染器.
有两种方案实现表头的折行渲染:
1、渲染器继承自JTextArea,实现TableCellRenderer接口,具体代码如下:
- import java.awt.Component;
- import java.awt.Dimension;
- import java.util.Enumeration;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
-
- import javax.swing.JTable;
- import javax.swing.JTextArea;
- import javax.swing.UIManager;
- import javax.swing.table.DefaultTableCellRenderer;
- import javax.swing.table.JTableHeader;
- import javax.swing.table.TableCellRenderer;
- import javax.swing.table.TableColumn;
- import javax.swing.table.TableColumnModel;
-
- public class TextAreaHeaderRenderer extends JTextArea implements
- TableCellRenderer {
- private final DefaultTableCellRenderer adaptee = new DefaultTableCellRenderer();
-
- private final Map cellSizes = new HashMap();
-
- public TextAreaHeaderRenderer() {
- setLineWrap(true);
- setWrapStyleWord(true);
- setHighlighter(null);
- }
-
- public Component getTableCellRendererComponent(
-
- JTable table, Object obj, boolean isSelected, boolean hasFocus,
- int row, int column) {
-
- JTableHeader header = table.getTableHeader();
- setForeground(header.getForeground());
- setBackground(header.getBackground());
- setFont(header.getFont());
- setText(obj.toString());
- setBorder(UIManager.getBorder("TableHeader.cellBorder"));
-
- TableColumnModel columnModel = table.getColumnModel();
- int width = columnModel.getColumn(column).getWidth();
- setSize(width, 100000);
- int height_wanted = (int) getPreferredSize().getHeight();
- addSize(table, column, height_wanted);
- height_wanted = findTotalMaximumRowSize(table, column);
- if (height_wanted != header.getHeight()) {
-
- this.setSize(new Dimension(width, height_wanted));
- }
- return this;
- }
-
- private void addSize(JTable table, int column, int height) {
- Map cols = (Map) cellSizes.get(table);
- if (cols == null) {
- cellSizes.put(table, cols = new HashMap());
- }
- Map rowheights = (Map) cols.get(new Integer(column));
- if (rowheights == null) {
- cols.put(new Integer(column), rowheights = new HashMap());
- }
- rowheights.put(new Integer(column), new Integer(height));
- }
-
-
-
-
-
-
- private int findTotalMaximumRowSize(JTable table, int column) {
- int maximum_height = 0;
- Enumeration columns = table.getColumnModel().getColumns();
- while (columns.hasMoreElements()) {
- TableColumn tc = (TableColumn) columns.nextElement();
- TableCellRenderer cellRenderer = tc.getHeaderRenderer();
- if (cellRenderer instanceof TextAreaHeaderRenderer) {
- TextAreaHeaderRenderer tar = (TextAreaHeaderRenderer) cellRenderer;
- maximum_height = Math.max(maximum_height, tar
- .findMaximumRowSize(table, column));
- }
-
- }
- return maximum_height;
- }
-
- private int findMaximumRowSize(JTable table, int column) {
- Map rows = (Map) cellSizes.get(table);
- if (rows == null)
- return 0;
- Map rowheights = (Map) rows.get(new Integer(column));
- if (rowheights == null)
- return 0;
- int maximum_height = 0;
- for (Iterator it = rowheights.entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry) it.next();
- int cellHeight = ((Integer) entry.getValue()).intValue();
- maximum_height = Math.max(maximum_height, cellHeight);
- }
- return maximum_height;
- }
- }
import java.awt.Component;
import java.awt.Dimension;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class TextAreaHeaderRenderer extends JTextArea implements
TableCellRenderer {
private final DefaultTableCellRenderer adaptee = new DefaultTableCellRenderer();
/** map from table to map of rows to map of column heights */
private final Map cellSizes = new HashMap();
public TextAreaHeaderRenderer() {
setLineWrap(true);
setWrapStyleWord(true);
setHighlighter(null);
}
public Component getTableCellRendererComponent(
//
JTable table, Object obj, boolean isSelected, boolean hasFocus,
int row, int column) {
// 设置表头渲染时的一些属性参数
JTableHeader header = table.getTableHeader();
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
setText(obj.toString());
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
// This line was very important to get it working with JDK1.4
TableColumnModel columnModel = table.getColumnModel();
int width = columnModel.getColumn(column).getWidth();
setSize(width, 100000);
int height_wanted = (int) getPreferredSize().getHeight();
addSize(table, column, height_wanted);
height_wanted = findTotalMaximumRowSize(table, column);
if (height_wanted != header.getHeight()) {
// 设置JTextArea的大小
this.setSize(new Dimension(width, height_wanted));
}
return this;
}
private void addSize(JTable table, int column, int height) {
Map cols = (Map) cellSizes.get(table);
if (cols == null) {
cellSizes.put(table, cols = new HashMap());
}
Map rowheights = (Map) cols.get(new Integer(column));
if (rowheights == null) {
cols.put(new Integer(column), rowheights = new HashMap());
}
rowheights.put(new Integer(column), new Integer(height));
}
/**
* Look through all columns and get the renderer. If it is also a
* TextAreaRenderer, we look at the maximum height in its hash table for
* this row.
*/
private int findTotalMaximumRowSize(JTable table, int column) {
int maximum_height = 0;
Enumeration columns = table.getColumnModel().getColumns();
while (columns.hasMoreElements()) {
TableColumn tc = (TableColumn) columns.nextElement();
TableCellRenderer cellRenderer = tc.getHeaderRenderer();
if (cellRenderer instanceof TextAreaHeaderRenderer) {
TextAreaHeaderRenderer tar = (TextAreaHeaderRenderer) cellRenderer;
maximum_height = Math.max(maximum_height, tar
.findMaximumRowSize(table, column));
}
// System.out.println("aaa");
}
return maximum_height;
}
private int findMaximumRowSize(JTable table, int column) {
Map rows = (Map) cellSizes.get(table);
if (rows == null)
return 0;
Map rowheights = (Map) rows.get(new Integer(column));
if (rowheights == null)
return 0;
int maximum_height = 0;
for (Iterator it = rowheights.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
int cellHeight = ((Integer) entry.getValue()).intValue();
maximum_height = Math.max(maximum_height, cellHeight);
}
return maximum_height;
}
}
此种渲染器的缺点是没有办法实现居中对齐。
2、因为JLabel可以解析html中的br,所以利用这个特点,可以动态构建显示的标题,在换行处添加<br>标记,实现换行显示,代码如下:
- import java.awt.Component;
- import java.awt.Dimension;
- import java.awt.FontMetrics;
-
- import javax.swing.JLabel;
- import javax.swing.JTable;
- import javax.swing.UIManager;
- import javax.swing.table.DefaultTableCellRenderer;
- import javax.swing.table.JTableHeader;
- import javax.swing.table.TableColumnModel;
-
- public class HeaderRendererHh extends DefaultTableCellRenderer {
-
- public Component getTableCellRendererComponent(JTable table, Object value,
- boolean isSelected, boolean hasFocus, int row, int column) {
-
- JTableHeader header = table.getTableHeader();
- setForeground(header.getForeground());
- setBackground(header.getBackground());
- setFont(header.getFont());
- setOpaque(true);
- setBorder(UIManager.getBorder("TableHeader.cellBorder"));
-
-
- TableColumnModel columnModel = table.getColumnModel();
- int width = columnModel.getColumn(column).getWidth();
-
- value = getShowValue(value.toString(), width);
- setText(value.toString());
- setSize(new Dimension(width, this.getHeight()));
-
- setHorizontalAlignment(JLabel.CENTER);
-
- return this;
- }
-
- private Object getShowValue(String value, int colWidth) {
-
- FontMetrics fm = this.getFontMetrics(this.getFont());
- int width = fm.stringWidth(value.toString());
- int test = fm.stringWidth("好");
- System.out.println(test * value.length());
- System.out.println(width);
- if (width < colWidth) {
- return value;
- }
- StringBuffer sb = new StringBuffer("<html>");
- char str;
- int tempW = 0;
- for (int i = 0; i < value.length(); i++) {
- str = value.charAt(i);
- tempW += fm.charWidth(str);
- if (tempW > colWidth) {
- sb.append("<br>");
- tempW = 0;
- }
- sb.append(str);
- }
- sb.append("</html>");
- return sb.toString();
- }
- }
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
public class HeaderRendererHh extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
JTableHeader header = table.getTableHeader();
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
setOpaque(true);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
// 得到列的宽度
TableColumnModel columnModel = table.getColumnModel();
int width = columnModel.getColumn(column).getWidth();
value = getShowValue(value.toString(), width);
setText(value.toString());
setSize(new Dimension(width, this.getHeight()));
setHorizontalAlignment(JLabel.CENTER);
return this;
}
private Object getShowValue(String value, int colWidth) {
// 根据当前的字体和显示值得到需要显示的宽度
FontMetrics fm = this.getFontMetrics(this.getFont());
int width = fm.stringWidth(value.toString());
int test = fm.stringWidth("好");
System.out.println(test * value.length());
System.out.println(width);
if (width < colWidth) {
return value;
}
StringBuffer sb = new StringBuffer("<html>");
char str;
int tempW = 0;
for (int i = 0; i < value.length(); i++) {
str = value.charAt(i);
tempW += fm.charWidth(str);
if (tempW > colWidth) {
sb.append("<br>");
tempW = 0;
}
sb.append(str);
}
sb.append("</html>");
return sb.toString();
}
}
两种方法在使用时只要给对应的列添加headerRenderer就可以了,如:
- HeaderRendererHh renderer = new HeaderRendererHh();
- TableColumnModel cmodel = table.getColumnModel();
- for (int i = 0; i < cmodel.getColumnCount(); i++) {
- cmodel.getColumn(i).setHeaderRenderer(renderer);
- }
下面方法是根据上面第二中方法来做的,因为我的表头换行的时候加了换行符号\n,方法如下:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
public class HeaderRendererHh extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
JTableHeader header = table.getTableHeader();
setForeground(header.getForeground());
setBackground(header.getBackground());
// setFont(header.getFont());
setFont(new Font(null, Font.BOLD, 13));
setOpaque(true);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
// 得到列的宽度
TableColumnModel columnModel = table.getColumnModel();
int width = columnModel.getColumn(column).getWidth();
value = getShowValue(value.toString(), width);
setText(value.toString());
setSize(new Dimension(width, this.getHeight()));
setHorizontalAlignment(JLabel.CENTER);
return this;
}
private Object getShowValue(String value, int colWidth) {
// 根据当前的字体和显示值得到需要显示的宽度
FontMetrics fm = this.getFontMetrics(this.getFont());
int width = fm.stringWidth(value.toString());
StringBuffer sb = new StringBuffer("<html>");
char str;
int tempW = 0;
for (int i = 0; i < value.length(); i++) {
str = value.charAt(i);
tempW += fm.charWidth(str);
char linebreak = '\n';
if (str == linebreak) {
sb.append("<br>");
tempW = 0;
}
sb.append(str);
}
sb.append("</html>");
return sb.toString();
}
}
在java文件中使用以上方法代码如下
HeaderRendererHh headrenderer = new HeaderRendererHh();// 设置Head居中
TableColumnModel cmodel = tabledata.getColumnModel();
for (int i = 0; i < cmodel.getColumnCount(); i++) {
cmodel.getColumn(i).setHeaderRenderer(headrenderer);
}
http://weibaojun.iteye.com/blog/524507