2014-05-19 1 views
2

JEditorPane을 사용하여 사용자가 텍스트를 입력 할 때 특정 색상 (예 : 녹색)으로 일부 텍스트를 표시하고 일부 부품의 색상을 변경하려고합니다. 예 : 특정 조건이 충족되면 (예 : 0 ~ 9 번째 문자 빨간색)JEditorPane의 텍스트의 특정 부분을 색칠하면 전경색 채색이 실패합니다.

그래서 기본적으로 기본 전경색이 필요하며 텍스트 색의 일부를 변경해야합니다. 지금까지 시도한 내용은 다음과 같습니다. 그러나 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을 사용하지 않는 이유 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) 내가 원하기 때문에 그것의 특정 부분에 착색하기 전에 모든 텍스트 흰색을 할 수 없습니다 바꿈 다음과 같이 내가 그것을 사용할 때 작동하지 beacause를 이유는 사용자가 텍스트를 입력하고 전체 텍스트가 SSCCE 에서처럼 기본적으로 흰색으로 표시되도록합니다. 키 문자 표시 장치 및 전체 흰색 문자를 문자 단위로 갖는 것은 아마도 너무 비효율적 일 것입니다. 기본적으로 특정 단어를 특정 단어와 일치 시키려면 colourrize하지만 SSCCE와 마찬가지로이 새롭고 편집 할 수없는 JTextPane/JEditorPane을 사용하면 문제를 해결할 수 있습니다.

다시 감사합니다 :)

+0

두 가지 방법이 있습니다 1. 형광펜 사용, 형광펜은 배열, 객체의 ParagraphAttributes에있는 2 개의 StyleConstants를 사용합니다. – mKorbel

+0

@mKorbel'형광펜 '은 전경이 아닌 배경색 만 변경합니다. – user1803551

+0

@ user1803551 (변경 가능) AttributeSet에서 파생 된 Highlighter에서 StyleConstants에 액세스 할 수 있습니다 (StanislavL의 ViewFactory는 HtmlEditorKit의 가능성 임) – mKorbel

답변

3

해결 방법 :JTextPane을 선택하는 대신 할 수있는 경우 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); 

와 함께 문제를 해결할 사용자 정의 색상을하기 전에 전체 텍스트의 전경색을 설정 JEditorPane 그러면 문제가 해결됩니다.

스크린 샷 :

enter image description here


편집

나는 JTextPane을 사용하지 않는 이유는. 이유는 그것을 사용하면 작동하지 않는 단어 배치가 beacause입니까?

다음은 사용자 정의 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

스크린 샷 :

이 자신의 지정된 각각의 색상으로 지정한 단어의 발생을 착색합니다 enter image description here

+0

+1, 텍스트 팬 (및 스타일이 지정된 텍스트)으로 작업하는 것이 JEditorPane (및 HTML)을 사용하는 것이 더 쉽다는 것을 알았습니다. – camickr

+0

@camickr 감사합니다. – Braj

+0

@Braj : 고맙습니다. 귀하가 요청한 정보를 추가하여 제 질문을 업데이트했습니다. 다시 한번 감사드립니다. D –

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(); 
    } 
} 

주 :

  • 이이 기능을 달성하기 위해 올바른 방법은 아마 하지,하지만 그게 내가 현재 무엇을 제공 할 수 있습니다.
  • 하나의 문제는 텍스트 편집기에서 텍스트를 추가하거나 제거 할 때마다 전체 내용을 포함하는 새로운 문자열이 만들어 지므로 큰 내용에는 비효율적입니다.
  • 더 큰 그림 (최종 목표)에 따라 성능, 기능 및 디자인 논리를 개선하려면이 구현을 수정해야합니다.
+0

@aspiring_sarge 문제가 해결 된 경우 받아 들여야합니다. – user1803551