2016-09-30 44 views
1

所以我有一個JTextPane,基本上作爲一個控制檯。我把它放在南部田地的JFrameJTextField的中心地帶。 JTextField將採用它所具有的文本,並在用戶按下Enter時將其添加到JTextPane。爲了使JTextPane不能被用戶編輯我不得不setFocusable(false),因爲使用setEditable(false)停止任何文字出現在JTextPane。但是,雖然我不希望用戶編輯窗格,但我仍然希望用戶能夠突出顯示窗格中的文本,但似乎無法找到實現此目的的方法。如何使用setFocusable(false)突出顯示JTextPane中的文本?

下面是證明了我的意思

樣品

package resources; 

import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.*; 
import javax.swing.border.EmptyBorder; 
import javax.swing.text.AttributeSet; 
import javax.swing.text.SimpleAttributeSet; 
import javax.swing.text.StyleConstants; 
import javax.swing.text.StyleContext; 

public class SampeTextPane extends JFrame 
{ 
    public SampeTextPane() 
    { 
     setPreferredSize(new Dimension(350, 200)); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 

     JTextPane display = new JTextPane(); 
     display.setBorder(new EmptyBorder(5, 5, 5, 5)); 
     display.setMargin(new Insets(5, 5, 5, 5)); 
     display.setFocusable(false); 
     appendToPane(display, "Example", Color.BLUE); 

     JTextField field = new JTextField(); 
     field.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 
       appendToPane(display, field.getText(), Color.BLACK); 
       field.setText(""); 
      } 
     }); 

     add(display, BorderLayout.CENTER); 
     add(field, BorderLayout.SOUTH); 

     pack(); 
     setVisible(true); 
    } 

    private void appendToPane(JTextPane pane, String text, Color color) 
    { 
     StyleContext sc = StyleContext.getDefaultStyleContext(); 
     AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, color); 

     aset = sc.addAttribute(aset, StyleConstants.Alignment, StyleConstants.ALIGN_JUSTIFIED); 

     int len = pane.getDocument().getLength(); 
     pane.setCaretPosition(len); 
     pane.setCharacterAttributes(aset, false); 
     pane.replaceSelection(text + "\n"); 
    } 

    public static void main(String[] args) 
    { 
     new SampeTextPane(); 
    } 
} 

預先感謝任何幫助的樣本。

回答

3

使用setEditable(false)可以停止在JTextPane中出現的任何文本。

您可以使JTextPane不可編輯,但不能通過文本窗格更新文本。

相反,你可以更新通過Document文:

//int len = pane.getDocument().getLength(); 
//pane.setCaretPosition(len); 
//pane.setCharacterAttributes(aset, false); 
//pane.replaceSelection(text + "\n"); 

try 
{ 
    StyledDocument doc = pane.getStyledDocument(); 
    doc.insertString(doc.getLength(), text, aset); 
} 
catch(BadLocationException e) { System.out.println(e); } 
+0

這完美地工作!謝謝 – Ryan

+0

...........並且比我的解決方案要乾淨得多。 1+ –

3

另一種選擇,雖然比較繞口,是使用一個布爾標誌以允許或禁止對文檔的更改,建議的東西StanislavL here

在您的情況,它可能看起來像:

import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.*; 
import javax.swing.border.EmptyBorder; 
import javax.swing.text.AttributeSet; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.DefaultStyledDocument; 
import javax.swing.text.DocumentFilter; 
import javax.swing.text.SimpleAttributeSet; 
import javax.swing.text.StyleConstants; 
import javax.swing.text.StyleContext; 

@SuppressWarnings("serial") 
public class SampeTextPane extends JFrame { 
    private boolean isApi = false; 

    public SampeTextPane() { 
     setPreferredSize(new Dimension(350, 200)); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 

     JTextPane display = new JTextPane(); 

     ((DefaultStyledDocument) display.getDocument()).setDocumentFilter(new DocFilter()); 

     display.setBorder(new EmptyBorder(5, 5, 5, 5)); 
     display.setMargin(new Insets(5, 5, 5, 5)); 
     // !! display.setFocusable(false); 
     appendToPane(display, "Example", Color.BLUE); 

     JTextField field = new JTextField(); 
     field.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 
       appendToPane(display, field.getText(), Color.BLACK); 
       field.setText(""); 
      } 
     }); 

     add(display, BorderLayout.CENTER); 
     add(field, BorderLayout.SOUTH); 

     pack(); 
     setVisible(true); 
    } 

    private void appendToPane(JTextPane pane, String text, Color color) { 
     isApi = true; 

     StyleContext sc = StyleContext.getDefaultStyleContext(); 
     AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, 
       color); 

     aset = sc.addAttribute(aset, StyleConstants.Alignment, StyleConstants.ALIGN_JUSTIFIED); 
     int len = pane.getDocument().getLength(); 

     String selection = pane.getSelectedText(); 
     if (selection == null) { 
      pane.setCaretPosition(len); 
      text += "\n"; 
     }   
     pane.setCharacterAttributes(aset, false); 
     pane.replaceSelection(text); 

     isApi = false; 
    } 

    private class DocFilter extends DocumentFilter { 
     @Override 
     public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) 
       throws BadLocationException { 
      if (isApi) { 
       super.insertString(fb, offset, string, attr); 
      } 
     } 

     @Override 
     public void remove(FilterBypass fb, int offset, int length) throws BadLocationException { 
      if (isApi) { 
       super.remove(fb, offset, length); 
      } 
     } 

     @Override 
     public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) 
       throws BadLocationException { 
      if (isApi) { 
       super.replace(fb, offset, length, text, attrs); 
      } 
     } 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> new SampeTextPane()); 
    } 

} 
+0

關於它的有趣的方式,並從我可以看到它做同樣的事情,但它略微超過了我的Java知識。雖然謝謝! – Ryan

+1

@瑞恩:是的,Camickr的建議更清潔,我很高興你能跟上。我在發佈他的正確答案之前創建了我的代碼,所以我討厭不發佈我的「努力」。當然,我做了他的答案。 –