2016-09-30 77 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的建议更清洁,我很高兴你能跟上。我在发布他的正确答案之前创建了我的代码,所以我讨厌不发布我的“努力”。当然,我做了他的答案。 –