Swing编程使用JTable表头换行显示

2011-04-19 13:53:57|?次阅读|上传:wustguangh【已有?条评论】发表评论

关键词:Java, Swing, 界面设计|来源:唯设编程网

在JTable渲染表头时,由于有些表头字体较多,需要折行显示,但JTable没有自动折行的功能,本文从网上搜集了两种实现JTable换行显示的方案,包括使用继承自JTextArea的渲染器和使用HTML标签,读者可以根据实际情况选用适合自己的方案。

1、渲染器继承自JTextArea,实现TableCellRenderer接口,具体代码如下:

Java代码

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、使用HTML标签<br>使表头文字换行

因为JLabel可以解析html中的br,所以利用这个特点,可以动态构建显示的标题,在换行处添加标记,实现换行显示,代码如下:

Java代码

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("");
		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("");
				tempW = 0;
			}
			sb.append(str);
		}
		sb.append("");
		return sb.toString();
	}
}

两种方法在使用时只要给对应的列添加headerRenderer就可以了,如:
Java代码

HeaderRendererHh renderer = new HeaderRendererHh();
TableColumnModel cmodel = table.getColumnModel();
for (int i = 0; i < cmodel.getColumnCount(); i++) {
    cmodel.getColumn(i).setHeaderRenderer(renderer);
}
发表评论0条 】
网友评论(共?条评论)..
Swing编程使用JTable表头换行显示