2016-09-30 5 views
1

Итак, у меня есть JTextPane, который в основном служит консолью. У меня это в центре поля JFrame и JTextField в южном поле. JTextField примет текст, который у него есть, и добавит его в JTextPane, когда пользователь нажимает кнопку ввода. Чтобы сделать JTextPane недоступным для редактирования пользователем, я должен был setFocusable(false), потому что с помощью setEditable(false) остановился любой текст, появляющийся на JTextPane. Но пока я не хочу, чтобы пользователь редактировал панель, мне все равно хотелось бы, чтобы пользователь мог выделить текст в панели, но я не могу найти способ сделать это.Как выделить текст в JTextPane с помощью setFocusable (false)?

Ниже приведен пример демонстрирует то, что я имею в виду

Sample

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 uneditable, но вы не можете обновить текст через текстовое поле.

Вместо этого вы можете обновить текст с помощью 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

@ Ryan: да, предложение Камикра ** намного чище, и я рад, что вы пошли с этим. Я создавал свой код, прежде чем он опубликовал свой правильный ответ, и поэтому мне не хотелось публиковать мои «усилия». Конечно, я проголосовал за его ответ. –