我希望使用JEditorPane以某种颜色(比如绿色)显示一些文本,当用户输入文本时,并在某些条件下更改某些部分的颜色(例如:第0到第9个字符为红色)满足了。
所以基本上,我需要一个默认的前景色,并且需要动态改变文本颜色的某些部分。到目前为止,我的尝试如下。但是,setForeground()方法似乎无法解决问题。我该如何解决这个问题?遗憾的是,使用类似JTextPane的东西不是一种选择,因为JTextPane中的一些问题使得它不适合我正在处理的事情。谢谢!
SSCCE:
public class ColoredStrikeThroughText {
public ColoredStrikeThroughText() {
JFrame fr = new JFrame("Custom color attribute");
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JEditorPane pane = new JEditorPane();
pane.setForeground(Color.GREEN);
pane.setEditorKit(new StyledEditorKit() {
public ViewFactory getViewFactory() {
return new NewViewFactory();
}
});
pane.setText("Color red text, color blue text, text without coloring.");
StyledDocument doc = (StyledDocument) pane.getDocument();
MutableAttributeSet attr = new SimpleAttributeSet();
StyleContext sc = StyleContext.getDefaultStyleContext();
AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, Color.red);
attr.addAttributes(aset);
doc.setCharacterAttributes(0, 9, attr, false);
aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, Color.blue);
attr.addAttributes(aset);
doc.setCharacterAttributes(17, 27, attr, false);
JScrollPane sp = new JScrollPane(pane);
fr.getContentPane().add(sp);
fr.setSize(300, 300);
fr.setLocationRelativeTo(null);
fr.setVisible(true);
}
public static void main(String[] args) {
ColoredStrikeThroughText test = new ColoredStrikeThroughText();
}
}
class NewViewFactory implements ViewFactory {
public View create(Element elem) {
String kind = elem.getName();
if (kind != null) {
if (kind.equals(AbstractDocument.ContentElementName)) {
return new LabelView(elem);
} else if (kind.equals(AbstractDocument.ParagraphElementName)) {
return new ParagraphView(elem);
} else if (kind.equals(AbstractDocument.SectionElementName)) {
return new BoxView(elem, View.Y_AXIS);
} else if (kind.equals(StyleConstants.ComponentElementName)) {
return new ComponentView(elem);
} else if (kind.equals(StyleConstants.IconElementName)) {
return new IconView(elem);
}
}
// default to text display
return new LabelView(elem);
}
}
class MyLabelView extends LabelView {
public MyLabelView(Element elem) {
super(elem);
}
}
编辑1:
谢谢大家。我担心我的问题没有澄清一些事情。因为我担心这个问题可能会变得太长,所以我把这些东西都遗漏了,但是我会在这里发布,因为似乎没有其他方法可以澄清:
1)为什么我没有使用JTextPane。原因是当我使用它时,自动换行不能正常工作:
SSCCE:
public class nowrapsscce extends JPanel{
public nowrapsscce() {
JFrame j = new JFrame();
JEditorPane inputPane = new JEditorPane(); //replace JEditorPane with
//JTextPane here to see how word wrapping fails
inputPane.setBackground(Color.BLACK);
inputPane.setForeground(Color.LIGHT_GRAY);
inputPane.setCaretColor(Color.LIGHT_GRAY);
JEditorPane noninputPane = new JEditorPane();
noninputPane.setEditable(false);
noninputPane.setText("Test ");
noninputPane.setPreferredSize(new Dimension(40, 200));
noninputPane.setBackground(Color.WHITE);
noninputPane.setForeground(Color.BLACK);
JPanel promptInputPanel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.LINE_START;
c.fill = GridBagConstraints.VERTICAL;
c.weighty = 1.0;
c.weightx = 0;
promptInputPanel.add(noninputPane, c);
c.anchor = GridBagConstraints.LINE_END;
c.gridwidth = GridBagConstraints.REMAINDER;
c.weightx = 1.0;
c.fill = GridBagConstraints.BOTH;
promptInputPanel.add(inputPane, c);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBorder(new EtchedBorder());
scrollPane.setViewportView(promptInputPanel);
scrollPane
.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
j.add(scrollPane);
j.setVisible(true);
j.pack();
}
public static void main(String[] args) {
nowrapsscce test = new nowrapsscce();
}
}
2)我不能将所有文本变为白色,然后在它的某些部分着色,因为我希望用户输入文本,并且默认情况下整个文本显示为白色,就像在SSCCE中一样。拥有一个keylistener并且逐个字符的整个白色字符可能效率太低。如果某些单词与给定的单词匹配,我想基本上对其进行着色,但是在侧面使用这个新的,不可编辑的JTextPane / JEditorPane,就像在SSCCE中一样,这是问题的转折。
再次感谢:)
答案 0 :(得分:3)
解决方法:在执行任何自定义着色之前设置整个文本的前景色将解决您的问题JEditorPane
AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY,
StyleConstants.Foreground,Color.GREEN);
attr.addAttributes(aset);
// set foreground for all the text
doc.setCharacterAttributes(0, pane.getText().length(), attr, false);
如果您可以选择JTextPane
而不是JEditorPane
,那么它将解决问题。
截图:
修改强>
为什么我没有使用
JTextPane
。原因是当我使用它时,自动换行无效?
这是自定义JTextPane
类。您可以尝试使用此类来解决包装问题。
示例代码:
public class NonWrappingTextPane extends JTextPane {
public NonWrappingTextPane() {
super();
}
public NonWrappingTextPane(StyledDocument doc) {
super(doc);
}
// Override getScrollableTracksViewportWidth
// to preserve the full width of the text
public boolean getScrollableTracksViewportWidth() {
Container parent = getParent();
ComponentUI ui = getUI();
return parent != null ? (ui.getPreferredSize(this).width <= parent.getSize().width) : true;
}
}
在此处查找完整代码Non Wrapping(Wrap) TextPane
截图:
答案 1 :(得分:1)
这将使用指定的相应颜色对指定单词的出现进行着色:
public class Colorer extends JFrame {
Pattern pat;
Map<String, SimpleAttributeSet> map = new HashMap<>();
JEditorPane editor = new JEditorPane();
public Colorer() {
String[] words = {"atext1", "atext", "text1"};
Color[] colors = {Color.RED, Color.GREEN, Color.BLUE};
StringBuilder sb = new StringBuilder(); // You can use words.length*8 in the constructor argument to estimate the capacity.
for (int i = 0; i < words.length; i++) {
sb.append("("+words[i]+")" + "|");
SimpleAttributeSet sas = new SimpleAttributeSet();
StyleConstants.setForeground(sas, colors[i]);
map.put(words[i], sas);
}
sb.deleteCharAt(sb.length()-1);
pat = Pattern.compile(sb.toString());
editor.setEditorKit(new StyledEditorKit());
editor.setDocument(new DefaultStyledDocument());
editor.getDocument().addDocumentListener(new ColorDocumentLister());
getContentPane().add(new JScrollPane(editor));
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
private class ColorDocumentLister implements DocumentListener {
SimpleAttributeSet black = new SimpleAttributeSet();
ColorDocumentLister() {
StyleConstants.setForeground(black, Color.BLACK);
}
public void insertUpdate(DocumentEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
finaAndColor();
}
});
}
public void removeUpdate(DocumentEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
finaAndColor();
}
});
}
public void changedUpdate(DocumentEvent e) {
}
private void finaAndColor() {
StyledDocument doc = (StyledDocument) editor.getDocument();
doc.setCharacterAttributes(0, doc.getLength(), black, true);
Matcher m = pat.matcher(editor.getText());
while (m.find()) {
doc.setCharacterAttributes(m.start(), m.end(), map.get(m.group()), true);
doc.setCharacterAttributes(m.end(), doc.getLength(), black, true);
}
}
}
public static void main(String[] args) {
new Colorer();
}
}
备注:强>