【问题标题】:How to make the end of a JTextArea editable如何使 JTextArea 的结尾可编辑
【发布时间】:2018-03-17 13:46:19
【问题描述】:

有没有办法使 JTextArea 的结尾可编辑,并使已打印到其中的任何内容不可编辑?

我的意思是,如果我已经将“Hello World”写到了 JTextArea,我怎么能做到这样用户可以在“Hello World”之后输入他们想要的任何内容,但在此之前他们不能输入还是删除已经打印好的文字?

下面是一个小程序来演示我的烦恼...

public class Test {
    public static void main(String[] args) {
        //Here I create a simple JFrame with JTextArea
        JTextArea textArea = new JTextArea();
        JFrame frame = new JFrame();
        JFrame.setDefaultLookAndFeelDecorated(true);
        frame.setSize(250, 250);
        textArea.setEditable(true);
        textArea.setVisible(true);
        frame.add(textArea);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


        /*Here I print "Hello World" onto the text area.. after the ">>" I want the
        the user to be able to type whatever they want.. however I don't want them
        to be able to edit the "Hello World"*/
        textArea.append("Hello World\n>>");
        textArea.setCaretPosition(textArea.getDocument().getLength());
    }
}

在示例中,用户可以输入他们想要的任何文本..这是我想要的..但​​是他们也能够编辑我使用 append.. 打印的文本我不想要..

我该如何解决这个问题?

【问题讨论】:

  • DocumentFilter 可能会起作用。我会尝试一下。
  • 还演示了here ;)

标签: java swing jtextarea


【解决方案1】:

是的,DocumentFilter 可以工作。创建一个仅在添加位于文档末尾时才允许添加文本的文本 - 也就是说,如果偏移量等于文档的长度。也完全停用删除方法。像这样:

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;

public class MyFilter extends DocumentFilter {
    @Override
    public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr)
            throws BadLocationException {
        // only insert text if at the end of the document
        // if offset == document length
        if (offset == fb.getDocument().getLength()) {
            super.insertString(fb, offset, string, attr);
        }
    }

    @Override
    public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
            throws BadLocationException {
        // only replace text if at the end of the document
        // if offset == document length
        if (offset == fb.getDocument().getLength()) {
            super.replace(fb, offset, length, text, attrs);
        }
    }

    @Override
    public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
        // do nothing. Totally inactivate this
    }
}

你可以像这样测试它:

import javax.swing.*;
import javax.swing.text.PlainDocument;

@SuppressWarnings("serial")
public class LimitedTextArea extends JPanel {
    private JTextArea textArea = new JTextArea(15, 50);

    public LimitedTextArea() {
        // get textArea's Document and cast to PlainDocument:
        PlainDocument document = (PlainDocument) textArea.getDocument();
        // set the document's filter with "MyFilter"
        document.setDocumentFilter(new MyFilter());

        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        JScrollPane scrollPane = new JScrollPane(textArea);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        add(scrollPane);
    }

    private static void createAndShowGui() {
        LimitedTextArea mainPanel = new LimitedTextArea();

        JFrame frame = new JFrame("LimitedTextArea");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

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

【讨论】:

    【解决方案2】:

    您也可以使用NavigationFilter

    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.text.*;
    
    public class NavigationFilterPrefix extends NavigationFilter
    {
        private int prefixLength;
        private Action deletePrevious;
    
        public NavigationFilterPrefix(int prefixLength, JTextComponent component)
        {
            this.prefixLength = prefixLength;
            deletePrevious = component.getActionMap().get("delete-previous");
            component.getActionMap().put("delete-previous", new BackspaceAction());
            component.setCaretPosition(prefixLength);
        }
    
        @Override
        public void setDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias)
        {
            fb.setDot(Math.max(dot, prefixLength), bias);
        }
    
        @Override
        public void moveDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias)
        {
            fb.moveDot(Math.max(dot, prefixLength), bias);
        }
    
        class BackspaceAction extends AbstractAction
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                JTextComponent component = (JTextComponent)e.getSource();
    
                if (component.getCaretPosition() > prefixLength)
                {
                    deletePrevious.actionPerformed( null );
                }
            }
        }
    
        private static void createAndShowUI()
        {
            JTextField textField = new JTextField("Prefix_", 20);
            textField.setNavigationFilter( new NavigationFilterPrefix(7, textField) );
    
            JFrame frame = new JFrame("Navigation Filter Example");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(textField);
            frame.pack();
            frame.setLocationRelativeTo( null );
            frame.setVisible(true);
        }
    
        public static void main(String[] args)
        {
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    createAndShowUI();
                }
            });
        }
    }
    

    这将允许用户编辑他们添加到文本字段的文本。

    这将阻止选择固定文本。

    如需更多高级功能,请查看Protected Document,它可让您保护文档的多个区域不被更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-14
      • 1970-01-01
      • 1970-01-01
      • 2014-12-11
      • 2012-09-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多