简体   繁体   English

如何使JTextArea的结尾可编辑

[英]How to make the end of a JTextArea editable

Is there a way to make the end of a JTextArea editable and make anything that has already been printed to it not editable? 有没有办法使JTextArea的结尾可编辑,并使已打印到它的任何内容都不可编辑?

What I mean by this is if I've written "Hello World" for example to a JTextArea, how could I make it so that the user can type in whatever they want after "Hello World" but they cannot type before that or delete the already printed text? 我的意思是,例如,如果我已经将“ Hello World”写到了JTextArea,我该如何做到这一点,以便用户可以在“ Hello World”之后输入所需内容,但不能在此之前输入或删除该内容。已经打印过的文字?

Below is a small program to demonstrate my troubles... 下面是一个演示我的麻烦的小程序...

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());
    }
}

In the example the user is able to enter whatever text they want.. which is what I want.. however they are also able to edit the text that I printed using append.. which I don't want.. 在该示例中,用户可以输入他们想要的任何文本..这就是我想要的..但​​是,他们也可以编辑使用我不想使用的append ..打印的文本。

How can I solve this? 我该如何解决?

Yes, a DocumentFilter will work. 是的,DocumentFilter可以使用。 Create one that only allows addition of text if the addition is at the end of the document -- that is if the offset equals the document's length. 创建一个仅允许在文本末尾添加文本(即,偏移量等于文档长度)的文本。 Also totally inactivate the remove method. 也完全取消了remove方法。 Something like so: 像这样:

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
    }
}

And you could test it like so: 您可以像这样测试它:

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());
    }
}

You could also use a NavigationFilter : 您还可以使用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();
            }
        });
    }
}

This will allow the user to edit the text they add to the text field. 这将允许用户编辑他们添加到文本字段中的文本。

This will prevent the fixed text from being selected. 这样可以防止选择固定文本。

For more advanced features, check out the Protected Document which allows you to protect multiple areas of the Document from being changed. 有关更高级的功能,请签出受保护的文档 ,该文档使您可以保护文档的多个区域不被更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM