我们正在实现一个非常小的信使,比如Java中的应用程序,并且正在使用JTextPane作为我们的消息面板。现在,我们正在尝试用.gif
文件替换常见的表情符号,我们使用一些可以完成工作的示例...除了图标居中对齐并且令人讨厌。反正有没有让它看起来内联(左对齐或正常)?一些帮助解决这个问题将不胜感激。
messagePane = new JTextPane();
messagePane.setEditable(false);
messagePane.setEditorKit(new WrapHTMLEditorKit());
messagePane.setContentType("text/html");
MessageDocument doc = new MessageDocument();
doc.addDocumentListener(new SmileyDocumentListener(messagePane));
messagePane.setStyledDocument(doc);
MessageDocument
类:public class MessageDocument extends HTMLDocument {
static private String NEW_LINE = System.getProperty("line.separator");
static private SimpleAttributeSet DEFAULT_STYLE = new SimpleAttributeSet();
static private SimpleAttributeSet ANNOUNCE_GLOBAL_STYLE = new SimpleAttributeSet();
static private SimpleAttributeSet MESSAGE_GLOBAL_STYLE = new SimpleAttributeSet();
static private SimpleAttributeSet MESSAGE_PRIVATE_STYLE = new SimpleAttributeSet();
static private SimpleAttributeSet ERROR_STYLE = new SimpleAttributeSet();
static{
StyleConstants.setFontFamily(DEFAULT_STYLE, "Courier New");
StyleConstants.setItalic(DEFAULT_STYLE, true);
StyleConstants.setForeground(DEFAULT_STYLE, Color.black);
StyleConstants.setFontFamily(ANNOUNCE_GLOBAL_STYLE, "Courier New");
StyleConstants.setBold(ANNOUNCE_GLOBAL_STYLE, true);
StyleConstants.setForeground(ANNOUNCE_GLOBAL_STYLE, new Color(0, 100, 0));
StyleConstants.setFontFamily(MESSAGE_GLOBAL_STYLE, "Courier New");
StyleConstants.setForeground(MESSAGE_GLOBAL_STYLE, Color.blue);
StyleConstants.setFontFamily(MESSAGE_PRIVATE_STYLE, "Courier New");
StyleConstants.setForeground(MESSAGE_PRIVATE_STYLE, Color.black);
StyleConstants.setBackground(MESSAGE_PRIVATE_STYLE, new Color(220, 220, 255));
StyleConstants.setFontFamily(ERROR_STYLE, "Courier New");
StyleConstants.setForeground(ERROR_STYLE, Color.yellow);
StyleConstants.setBackground(ERROR_STYLE, Color.red);
}
public MessageDocument() {
super();
}
public void addMessage(ServerMessage msg) {
SimpleAttributeSet style;
if (MessageType.ANNOUNCE_GLOBAL.equals(msg.getType()) || MessageType.CONNECTION_EVENT.equals(msg.getType()) || MessageType.DISCONNECTION_EVENT.equals(msg.getType())) {
style = ANNOUNCE_GLOBAL_STYLE;
} else if (MessageType.MESSAGE_GLOBAL.equals(msg.getType())) {
style = MESSAGE_GLOBAL_STYLE;
} else if (MessageType.MESSAGE_PRIVATE.equals(msg.getType())) {
style = MESSAGE_PRIVATE_STYLE;
} else if (MessageType.ERROR.equals(msg.getType())) {
style = ERROR_STYLE;
} else {
style = DEFAULT_STYLE;
}
try {
insertString(getLength(), msg.getMessage() + NEW_LINE, style);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}
WrapHTMLEditorKit
类:public class WrapHTMLEditorKit extends HTMLEditorKit {
@Override
public ViewFactory getViewFactory() {
return new HTMLFactory() {
public View create(Element e) {
View v = super.create(e);
if (v instanceof InlineView) {
return new InlineView(e) {
public int getBreakWeight(int axis, float pos, float len) {
return GoodBreakWeight;
}
public View breakView(int axis, int p0, float pos, float len) {
if (axis == View.X_AXIS) {
checkPainter();
int p1 = getGlyphPainter().getBoundedPosition(this, p0, pos, len);
if (p0 == getStartOffset() && p1 == getEndOffset()) {
return this;
}
return createFragment(p0, p1);
}
return this;
}
};
} else if (v instanceof ParagraphView) {
return new ParagraphView(e) {
protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) {
if (r == null) {
r = new SizeRequirements();
}
float pref = layoutPool.getPreferredSpan(axis);
float min = layoutPool.getMinimumSpan(axis);
// Don't include insets, Box.getXXXSpan will include them.
r.minimum = (int) min;
r.preferred = Math.max(r.minimum, (int) pref);
r.maximum = Integer.MAX_VALUE;
r.alignment = 0.5f;
return r;
}
};
}
return v;
}
};
}
}
SmileyDocumentListener
类:public class SmileyDocumentListener implements DocumentListener {
private JTextComponent owner;
private HashMap<String,ImageIcon> smileMap;
public SmileyDocumentListener(JTextComponent owner) {
this.owner = owner;
this.smileMap = new HashMap<String, ImageIcon>();
this.smileMap.put(":)", new ImageIcon("resources/images/smileys/smile.gif"));
}
@Override
public void insertUpdate(DocumentEvent event) {
final DocumentEvent e = event;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (e.getDocument() instanceof StyledDocument) {
try {
StyledDocument doc=(StyledDocument)e.getDocument();
int start = Utilities.getRowStart(owner, Math.max(0, e.getOffset() - 1));
int end = Utilities.getWordStart(owner, e.getOffset() + e.getLength());
String text = doc.getText(start, end-start);
for (String token : smileMap.keySet()) {
int i = text.indexOf(token);
while (i >= 0) {
final SimpleAttributeSet attrs = new SimpleAttributeSet(doc.getCharacterElement(start + i).getAttributes());
if (StyleConstants.getIcon(attrs) == null) {
StyleConstants.setIcon(attrs, smileMap.get(token));
doc.remove(start + i, 2);
doc.insertString(start + i, token, attrs);
}
i = text.indexOf(token, i+token.length());
}
}
} catch (BadLocationException e1) {
e1.printStackTrace();
}
}
}
});
}
@Override
public void removeUpdate(DocumentEvent e) {}
@Override
public void changedUpdate(DocumentEvent e) {}
}
注意:我已尝试将r.alignment = 0.5f;
更改为0.0f
中的WrapHTMLEditorKit.java
答案 0 :(得分:2)
您可以尝试插入HTML标记“&lt; img ...&gt;”。选择文本并应用一些字符属性(例如粗体)以创建单独的叶元素。然后用IMG标记替换元素; HTML。
答案 1 :(得分:1)
好吧,所以我不知道为什么使用JTextPane
的内容类型在text/html
中以这种方式显示图标(我尝试使用显示图标的JLabel
,直接设置HTML等。)底线是我认为HTML是必要的。
我替换了
public class MessageDocument extends HTMLDocument {
通过
public class MessageDocument extends StyledDocument {
我删除了WrapHTMLEditorKit
并使用
messagePane = new JTextPane();
messagePane.setEditable(false);
messagePane.setEditorKit(new StyledEditorKit());
MessageDocument doc = new MessageDocument();
doc.addDocumentListener(new SmileyDocumentListener(messagePane));
messagePane.setStyledDocument(doc);
和图标正常显示。
内容包装时没有特殊的类,我仍然可以使用SimpleAttributeSet
个对象。