Вопрос по java, document, swing, jtextcomponent, jtextarea – Сделайте части JTextArea недоступными для редактирования (не всю JTextArea!)

10

В настоящее время я работаю над консольным окном в Swing. Он основан на JTextArea и работает как обычная командная строка. Вы вводите команду в одну строку и нажимаете ввод. На следующей строке показан вывод, и под этим выводом вы можете написать следующую команду.

Теперь я хочу, чтобы вы могли редактировать только текущую строку вашей командой. Все строки выше (старые команды и результаты) должны быть недоступны для редактирования. Как я могу это сделать?

Ваш Ответ

5   ответов
0

AFAIK, вам нужно реализовать свой собственный контроль

Возможно, вы могли бы смоделировать его с помощью списка текстовых полей (даже включенных и нечетных отключенных) или сочетания текстовых полей / меток

РЕДАКТИРОВАТЬ:

Я бы поспорил на нередактируемую текстовую область и редактируемое текстовое поле. Введите текстовое поле, нажмите клавишу ввода, добавьте & quot; команду & quot; и вывод в текстовое поле

16

Вам не нужно создавать свой собственный компонент.

Это можно сделать (как я это сделал), используя пользовательскийDocumentFilter.

Вы можете получить документ отtextPane.getDocument() и установить фильтр на негоdocument.setFilter(), Внутри фильтра вы можете проверить позицию подсказки и разрешить изменения, только если позиция находится после подсказки.

Например:

private class Filter extends DocumentFilter {
    public void insertString(final FilterBypass fb, final int offset, final String string, final AttributeSet attr)
            throws BadLocationException {
        if (offset >= promptPosition) {
            super.insertString(fb, offset, string, attr);
        }
    }

    public void remove(final FilterBypass fb, final int offset, final int length) throws BadLocationException {
        if (offset >= promptPosition) {
            super.remove(fb, offset, length);
        }
    }

    public void replace(final FilterBypass fb, final int offset, final int length, final String text, final AttributeSet attrs)
            throws BadLocationException {
        if (offset >= promptPosition) {
            super.replace(fb, offset, length, text, attrs);
        }
    }
}

Однако это не позволяет программно вставлять содержимое в выходной (нередактируемый) раздел терминала. Вместо этого вы можете использовать либо флаг прохода в вашем фильтре, который вы установили, когда собираетесь добавить вывод, либо (что я сделал) установить фильтр документов на ноль перед добавлением вывода, а затем сбросить его, когда вы & apos; сделано.

((AbstractDocument) jta.getDocument ()) setDocumentFilter (dfilter).
3
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class OnlyEditCurrentLineTest {
  public JComponent makeUI() {
    JTextArea textArea = new JTextArea(8,0);
    textArea.setText("> aaa\n> ");
    ((AbstractDocument)textArea.getDocument()).setDocumentFilter(
        new NonEditableLineDocumentFilter());
    JPanel p = new JPanel(new BorderLayout());
    p.add(new JScrollPane(textArea), BorderLayout.NORTH);
    return p;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() { createAndShowGUI(); }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new OnlyEditCurrentLineTest().makeUI());
    f.setSize(320,240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}
class NonEditableLineDocumentFilter extends DocumentFilter {
  @Override public void insertString(
      DocumentFilter.FilterBypass fb, int offset, String string,
      AttributeSet attr) throws BadLocationException {
    if(string == null) {
      return;
    }else{
      replace(fb, offset, 0, string, attr);
    }
  }
  @Override public void remove(
      DocumentFilter.FilterBypass fb, int offset,
      int length) throws BadLocationException {
    replace(fb, offset, length, "", null);
  }
  private static final String PROMPT = "> ";
  @Override public void replace(
      DocumentFilter.FilterBypass fb, int offset, int length,
      String text, AttributeSet attrs) throws BadLocationException {
     Document doc = fb.getDocument();
     Element root = doc.getDefaultRootElement();
     int count = root.getElementCount();
     int index = root.getElementIndex(offset);
     Element cur = root.getElement(index);
     int promptPosition = cur.getStartOffset()+PROMPT.length();
     //As Reverend Gonzo says:
     if(index==count-1 && offset-promptPosition>=0) {
       if(text.equals("\n")) {
         String cmd = doc.getText(promptPosition, offset-promptPosition);
         if(cmd.isEmpty()) {
           text = "\n"+PROMPT;
         }else{
           text = "\n"+cmd+"\n    xxxxxxxxxx\n" + PROMPT;
         }
       }
       fb.replace(offset, length, text, attrs);
     }
  }
}
-1

Как насчет этого, когда & gt; & gt; & Quot; это начало каждой строки в командной строке, где пользователь может ввести команду:

textArea.addKeyListener(new KeyAdapter() {

    public void keyPressed(KeyEvent event) {

        int code = event.getKeyCode();          
        int caret = textArea.getCaretPosition();
        int last = textArea.getText().lastIndexOf(">> ") + 3;

        if(caret <= last) {

            if(code == KeyEvent.VK_BACK_SPACE) {

                textArea.append(" ");

                textArea.setCaretPosition(last + 1);
            }

            textArea.setCaretPosition(textArea.getText().length());
         }
     }
 });
-1 для keyListener -far слишком низкого уровня, чтобы удовлетворить требование безопасно
+1 KeyListener - это самый простой способ реализовать такую функциональность, никаких проблем с безопасностью я использую KeyListener уже много лет.
0

Это моя реализация фильтра документов, выступающего в роли консоли в Java. Однако с некоторыми изменениями, чтобы я мог иметь & quot; область команд & quot; и «область журнала», означающая результаты команд, напечатанных в области журнала, и фактических команд, напечатанных в области команд. Область журнала - это просто еще одна область Jtext, которую нельзя редактировать. Я нашел это полезным, поэтому кто-то, пытающийся достичь чего-то похожего на эту реализацию, может найти несколько указателей!

class NonEditableLineDocumentFilter extends DocumentFilter 
{
    private static final String PROMPT = "Command> ";

    @Override 
    public void insertString(DocumentFilter.FilterBypass fb, int offset, String string,AttributeSet attr) throws BadLocationException 
    {
        if(string == null) 
        {
            return;
        }
        else
        {
            replace(fb, offset, 0, string, attr);
        }   
    }

    @Override 
    public void remove(DocumentFilter.FilterBypass fb, int offset,int length) throws BadLocationException 
    {
        replace(fb, offset, length, "", null);
    }

    @Override 
    public void replace(DocumentFilter.FilterBypass fb, int offset, int length,String text, AttributeSet attrs) throws BadLocationException 
    {     
        Document doc = fb.getDocument();
        Element root = doc.getDefaultRootElement();
        int count = root.getElementCount();
        int index = root.getElementIndex(offset);
        Element cur = root.getElement(index);
        int promptPosition = cur.getStartOffset()+PROMPT.length();

        if(index==count-1 && offset-promptPosition>=0) 
        {
            if(text.equals("\n")) 
            {
                cmd = doc.getText(promptPosition, offset-promptPosition);

                if(cmd.trim().isEmpty()) 
                {
                    text = "\n"+PROMPT;
                }
                else
                {
                    text = "\n" + PROMPT;
                }
            }
            fb.replace(offset, length, text, attrs);
        }
    }
}

Похожие вопросы