这是使用上述代码的 SimpleHTMLJLabel 的修改版本
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.IOException;
import java.io.StringReader;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import javax.swing.JLabel;
import javax.swing.border.Border;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML.Tag;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
public class SimpleHTMLJLabel extends JLabel {
private static final String ellipsis = "...";
private static final String Set = null;
private int textproperwidth;
private FontMetrics fontMetrics;
private int ellipsisWidth;
private int insetsHorizontal;
private int borderHorizontal;
private List<Entry<String, String>> lines;
static String HTML = "<HTML>";
public SimpleHTMLJLabel() {
insetsHorizontal = getInsets().left + getInsets().right;
fontMetrics = getFontMetrics(getFont());
calculateWidths();
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
int availablewidth = getWidth();
renderHtml(availablewidth);
}
});
}
public SimpleHTMLJLabel(String text) {
this();
setText(text);
}
public SimpleHTMLJLabel(List<Entry<String, String>> lines) {
this();
this.lines = lines;
calculateWidths();
super.setText(HTML + toHtml(lines));
}
@Override
public void setText(String text) {
if (text.toUpperCase().startsWith(HTML)) {
this.lines = parseHtml(text);
calculateWidths();
super.setText(HTML + toHtml(lines));
return;
}
super.setText(text);
}
private List<Entry<String, String>> parseHtml(String text) {
List<Entry<String, String>> ret = new ArrayList<>();
java.util.Map<Tag, MutableAttributeSet> tags = new HashMap<>();
try {
(new javax.swing.text.html.parser.ParserDelegator()).parse(new StringReader(text), new ParserCallback() {
@Override
public void handleEndTag(Tag t, int pos) {
//TODO clean handle MutableAttributeSet a
tags.remove(t);
}
@Override
public void handleStartTag(javax.swing.text.html.HTML.Tag t, MutableAttributeSet a, int pos) {
if (t == Tag.HTML) return;
if (t == Tag.P) return;
if (t == Tag.BR) return;
if (t == Tag.BODY) return;
tags.put(t,a);
}
@Override
public void handleText(char[] data, int pos) {
String formats = tags.entrySet().stream().map(t -> "<" + t.getKey() + getAttrib(t.getValue) + ">").collect(Collectors.joining());
ret.add(new AbstractMap.SimpleEntry<>(formats, new String(data)));
}
private String getAttrib(MutableAttributeSet t) {
// TODO Auto-generated method stub
//return " style='color:red'";
return " " + t;
}
}, false);
} catch (IOException e) {
e.printStackTrace();
}
return ret;
}
private static String toEndTag(String s) {
return s.replace("<", "</");
}
private static String toHtml(List<Entry<String, String>> lines) {
return lines.stream().map(s -> s.getKey() + s.getValue() + toEndTag(s.getKey())).collect(Collectors.joining());
}
private static String toPlain(List<Entry<String, String>> lines) {
return lines.stream().map(s -> s.getValue()).collect(Collectors.joining(" "));
}
static private List<Entry<String, String>> clipText(List<Entry<String, String>> properList) {
Entry<String, String> last = properList.get(properList.size() - 1);
List<Entry<String, String>> ret = properList.subList(0, properList.size() - 1);
String newlastValue = truncate(last.getValue());
if (newlastValue.isEmpty()) {
return ret;
}
List<Entry<String, String>> retNew = new ArrayList<>();
retNew.addAll(ret);
retNew.add(new AbstractMap.SimpleEntry<>(last.getKey(), newlastValue));
return retNew;
}
static private String truncate(String newlastValue) {
newlastValue = newlastValue.substring(0, newlastValue.length() - 1);
while (newlastValue.endsWith(" ")) {
newlastValue = newlastValue.substring(0, newlastValue.length() - 1);
}
return newlastValue;
}
private void calculateWidths() {
if (lines != null) {
textproperwidth = fontMetrics.stringWidth(toPlain(lines));
}
ellipsisWidth = fontMetrics.stringWidth(ellipsis);
}
@Override
public void setFont(Font font) {
super.setFont(font);
fontMetrics = getFontMetrics(getFont());
calculateWidths();
}
@Override
public void setBorder(Border border) {
super.setBorder(border);
borderHorizontal = border.getBorderInsets(this).left + border.getBorderInsets(this).right;
}
}
在 TableCellRenderer 中使用我的代码时,您需要在构造函数时立即调整大小,但是当您没有列的大小时:
public SimpleHTMLJLabel() {
...
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
int availablewidth = getWidth();
renderHtml(availablewidth);
}
});
}
protected void renderHtml(int availablewidth) {
if (lines == null || availablewidth == 0) return;
System.out.println("renderHtml " + textproperwidth + ">" + availablewidth);
if (textproperwidth > availablewidth - (insetsHorizontal + borderHorizontal)) {
List<Entry<String, String>> properList = clipText(lines);
while (properList.size() > 0 && fontMetrics.stringWidth(toPlain(properList)) + ellipsisWidth > availablewidth - (insetsHorizontal + borderHorizontal)) {
properList = clipText(properList);
}
SimpleHTMLJLabel.super.setText(HTML + toHtml(properList) + ellipsis);
} else {
SimpleHTMLJLabel.super.setText(HTML + toHtml(lines));
}
}
@Override
public void reshape(int x, int y, int w, int h) {
if (w > 0) renderHtml(w - 5);
super.reshape(x, y, w, h);
}
在 JTable 中
table = new JTable(model) {
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
TableColumn col = table.getColumnModel().getColumn(column);
javax.swing.table.DefaultTableCellRenderer.UIResource csss;
SimpleHTMLJLabel lab = new SimpleHTMLJLabel(((JLabel)
//lab.setXXX( c.getXXX)); for font bcolor, color, border, etc
lab.setText(c.getText());
lab.renderHtml(col.getWidth() - 5);
return lab;
}
};
可以复用html-labell组件来节省GC