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

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

  • 用户只能在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%的此function正常工作,但有一些错误,并且不知道如何实现上面的最后一项(突出显示的文本上的批量命令)。 这就是我所拥有的:

 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 = charMax) { ignoreInput = true; charCntLabel.setText("0 " + charsRemaining); } } }); 

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

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

问题

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

提前致谢。

您可以使用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"); } } } 

evt.consume(); 在这种情况下将帮助很多..你不需要使用DocumentFilter。 这是一种更容易限制用户一定长度的方法

 private void jTextArea1KeyTyped(java.awt.event.KeyEvent evt) { String s=jTextArea1.getText(); int l=s.length(); jTextField1.setText(String.valueOf(l)); int i=10-l; jTextField2.setText(String.valueOf(i)); try{ if(l>=10){evt.consume(); } } catch(Exception w){} } 

加上Ray S. Kan所说的话:

有一种更简单的方法来限制JTextArea的字符,而不必使用Ray S. Kan所示的DocumentFilter,但他的答案的问题是它不会阻止某人粘贴长文本。 以下内容将阻止用户粘贴内容以绕过限制:

 @Override public void keyTyped(KeyEvent e) { int max = 25; if(text.getText().length() > max+1) { e.consume(); String shortened = text.getText().substring(0, max); text.setText(shortened); }else if(text.getText().length() > max) { e.consume(); } } 

如果长度不是最大值,这将停止按键,但如果它超过最大值,它将简单地用较短的字符串替换文本区域中的字符串。 text变量是JTextArea swing对象。