使用一些曲线球在Swing JTextArea上强制使用最大字符

IAm*_*aja 1 java swing jtextarea

我正在尝试向Swing JLabel和JTextArea添加功能,以便:

  • 用户只允许在textarea中输入500个字符(最大)
  • 标签包含一个字符串消息,告诉用户他们剩下多少个字符(在每个键击或退格后)
  • 当组件初始化时,标签显示"最多500个字符!"
  • 对于输入的前500个字符,对于键入的每个击键(a - z,A - Z,0 - 9和标点符号),标签显示"剩余x个字符",其中x是字符到达之前剩余的字符数.最多500
  • 键入第500个字符时,标签显示"剩余0个字符",并且不能在文本区域中输入其他字符
  • 如果用户键入退格按钮(KeyEvent.VK_BACK_SPACE),它们会"释放"一个字符,并且计数会递增.因此,如果它们剩下400个字符,并且它们键入退格键,则标签现在显示为"剩余401个字符"
  • 如果用户突出显示一组字符并对它们执行批量命令(例如退格键,或用单个字符替换突出显示的文本),则将正确计算正确的剩余字符数,并更新标签.因此,如果他们剩下50个字符,并且他们突出显示5个字母并点击退格,他们现在有"剩下55个字符"

我有90%的此功能正常工作,但有一些错误,并且不知道如何实现上面的最后一项(突出显示的文本上的批量命令).这就是我所拥有的:

boolean ignoreInput = false;
int charMax = 500;
JLabel charCntLabel = getLabel();
JTextArea myTextArea = getTextArea();

myTextArea.addKeyListener(new KeyListener() {
    @Override
    public void keyTyped(KeyEvent e) {
        return;
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // If we should be ignoring input then set make sure we
        // enforce max character count and remove the newly typed key.
        if(ignoreInput)
            myTextArea.setText(myTextArea.getText().substring(0,
                myTextArea.getText().length()));
    }

    @Override
    public void keyPressed(KeyEvent e) {
        String charsRemaining = " characters remaining";
        int newLen = 0;

        // The key has just been pressed so Swing hasn't updated
        // the text area with the new KeyEvent.
        int currLen = myTextArea.getText().length();

        // Adjust newLen depending on whether the user just pressed
        // the backspace key or not.
        if(e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
            newLen = currLen - 1;
            ignoreInput = false;
        }
        else
            newLen = currLen + 1;

        if(newLen < 0)
            newLen = 0;

        if(newLen == 0)
            charCntLabel.setText(charMax + " characters maximum!");
        else if(newLen >= 0 && newLen < charMax)
            charCntLabel.setText((charMax - newLen) + charsRemaining);
        else if(newLen >= charMax) {
            ignoreInput = true;
            charCntLabel.setText("0 " + charsRemaining);
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

上面的代码工作得很好,但有一些错误:

  • 它不会阻止用户输入> 500个字符.当用户键入第500个字符时,标签显示"剩余0个字符".但是之后你可以继续输入字符,标签保持不变.
  • 如果textarea中有> 500个字符,并且您开始退格,则会看到每个字符都从textarea(基础模型)中删除,但标签保持不变.但是,一旦你足够退格以获得第500个字符,并且退格,标签将开始正确改变,告诉你你有"剩下1个字符","剩下2个字符"等等.所以......
  • 此代码似乎工作,但只是停止工作> 500个字符.一旦你回到500 char最大值,它就会重新开始工作.

问题

  1. 有没有更简单的方法来实现这个所需的功能(以及Swing JTextArea)?我觉得我在这里重新发明轮子,并且可能有一种"更清洁"的方式来强制执行角色最大值并更新各自的标签.
  2. 如果没有,任何人都可以发现我的> 500 char bug?我整个上午都在看着它,我正在拔头发.
  3. 最重要的是,如何实现我的要求来处理突出显示文本的批量命令?如何在文本区域内处理文本选择,监听突出显示文本的更改(例如,使用退格按钮删除多个突出显示的字符等),并正确计算剩余字符的新值?

提前致谢.

Jos*_*ior 10

您可以使用DocumentFilter限制最大大小,请查看此文档部分,它有一个您需要的工作示例.

以此为例,我使用了上面示例文件中的组件:

import java.awt.BorderLayout;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;

import components.DocumentSizeFilter;

public class Test {

    public static void main(String[] args) {
        new TestFrame().setVisible(true);
    }

    private static class TestFrame extends JFrame{
        private JTextField textField;
        private DefaultStyledDocument doc;
        private JLabel remaningLabel = new JLabel();

        public TestFrame() {
            setLayout(new BorderLayout());

            textField = new JTextField();
            doc = new DefaultStyledDocument();
            doc.setDocumentFilter(new DocumentSizeFilter(500));
            doc.addDocumentListener(new DocumentListener(){
                @Override
                public void changedUpdate(DocumentEvent e) { updateCount();}
                @Override
                public void insertUpdate(DocumentEvent e) { updateCount();}
                @Override
                public void removeUpdate(DocumentEvent e) { updateCount();}
            });
            textField.setDocument(doc);

            updateCount();

            add(textField, BorderLayout.CENTER);
            add(remaningLabel, BorderLayout.SOUTH);

            setLocationRelativeTo(null);
            pack();
        }

        private void updateCount()
        {
            remaningLabel.setText((500 -doc.getLength()) + " characters remaining");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么没有更直接的方式奇怪没有方法为tha (2认同)