Hacer cumplir máximo de caracteres en el Columpio JTextArea con un par de bolas curvas

Estoy tratando de agregar funcionalidad a un Columpio JLabel y JTextArea tales que:

  • El usuario sólo puede entrar a 500 caracteres en el textarea (max)
  • La etiqueta contiene una cadena de mensaje indicando al usuario cómo muchos de los personajes que han dejado (después de cada golpe de tecla o la tecla de retroceso)
  • Cuando los componentes inicializar la etiqueta dice «500 caracteres máximo!»
  • Para los primeros 500 caracteres tecleados, por cada pulsación de tecla (a – z, a – Z, 0 – 9, y signos de puntuación) escribió, lee la etiqueta «x caracteres restantes», donde x es el número de caracteres que tiene a la izquierda antes de llegar al máximo de 500
  • Cuando los 500 caracteres se escribe, lee la etiqueta «0 caracteres restantes», y no hay más caracteres que puede ser escrito en el área de texto
  • Si el usuario escribe la tecla backspace (KeyEvent.VK_BACK_SPACE), que «libre» del personaje, y el número de incrementos. Por lo tanto si tenían 400 caracteres restantes, y que tipo de retroceso, ahora la etiqueta dice «401 caracteres restantes»
  • Si el usuario pone de relieve un conjunto de caracteres y realiza una masiva comando en ellos (como un retroceso, o reemplazar el texto resaltado con un solo carácter), la correcta # de caracteres restantes se calculará correctamente y la etiqueta será actualizado. Así que si tienen 50 caracteres restantes, y destacan por 5 cartas y pulsa la tecla de retroceso, que ahora tienen «55 caracteres restantes»

Tengo el 90% de esta funcionalidad, pero tiene un par de bugs, y no tienen ni idea de cómo implementar el último ítem (a granel comandos en el texto resaltado). He aquí lo que tengo:

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

El código anterior funciona bastante bien, pero tiene un par de fallos:

  • No impide que el usuario escriba en > 500 caracteres. Cuando el usuario escribe en el 500 caracteres, lee la etiqueta «0 caracteres restantes.» Pero usted puede seguir para escribir en caracteres después de eso, y la etiqueta permanece el mismo.
  • Si usted tiene > 500 caracteres en la caja de texto, y empezar retroceso, podrás ver cada uno de los caracteres de ser retirado de la caja de texto (el modelo subyacente), pero la etiqueta sigue siendo el mismo. Pero, una vez que la tecla de retroceso suficiente para llegar a los 500 personaje, y el retroceso, la etiqueta va a empezar a cambiar correctamente, que te dice que tienes «1 caracteres restantes», «2 caracteres restantes», etc. Así que…
  • Este código parece que funciona, pero simplemente deja de funcionar > 500 caracteres. Una vez que usted consigue de nuevo dentro de 500 char max, comienza a trabajar de nuevo.

Las preguntas

  1. Hay una forma más simple para implementar esta funcionalidad deseada (y para un Swing JTextArea)? Me siento como que me estoy reinventando la rueda de aquí y que podría ser un «limpiador» manera de hacer cumplir carácter de máximos y actualización de sus respectivas etiquetas.
  2. Si no, ¿alguien puede irregular mi > 500 char error? He estado mirando toda la mañana y estoy tirando de mi pelo.
  3. Lo que es más importante, ¿cómo puedo aplicar mi requisito para manejo de cargas a granel de los comandos de resaltado de texto? ¿Cómo puedo selecciones de texto dentro de la caja de texto, a escuchar los cambios en el texto resaltado (por ejemplo, la eliminación de varios de relieve los caracteres con la tecla backspace, etc.), y calcular correctamente el nuevo valor para los caracteres restantes?

Gracias de antemano.

  • Usted es lo que es bastante complicado para ti. No cuente los caracteres que se escriben, sencillo comprobar cuántos personajes hay en el JTextArea utilizando (por ejemplo) getText(). La limitación de la cantidad que se puede introducir es un problema diferente, que puede ser resuelto por la prestación de su propio documento (modelo) para el JTextArea.
InformationsquelleAutor IAmYourFaja | 2012-12-13

3 Kommentare

  1. 10

    Puede limitar el tamaño máximo mediante el uso de un DocumentFilter, marque esta sección de documentación, tiene un ejemplo de trabajo de lo que usted necesita.

    Tomar esto como un ejemplo, he utilizado el componente desde el archivo de ejemplo de arriba:

    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");
            }
        }
    }
    • tal vez usar JOptionPane en el caso de que el Documento se plantea máximo de caracteres,
    • Gracias @Jose (+1) – gran sugerencia, sin embargo, yo no estoy viendo donde puedo encontrar DocumentSizeFilter desde cualquiera de esos enlaces. ¿Sabes lo de la biblioteca, necesito añadir? Gracias de nuevo!
    • En el ejemplo de trabajo el enlace: docs.oracle.com/javase/tutorial/uiswing/examples/components/…
    • Hermoso – trabajó como un encanto, gracias!!
    • Por qué no hay más directa manera extraña, no existe ningún método para tha
  2. 2

    evt.consumen(); va a ayudar mucho en este caso..usted no necesita utilizar DocumentFilter. aquí está una manera mucho más fácil de limitar al usuario a cierta longitud

    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){}
    
    } 
  3. 1

    Para agregar a lo que Ray S. Kan dijo:

    Hay una forma más fácil de limitar los caracteres de un JTextArea sin tener que utilizar un DocumentFilter como se muestra por Ray S. Kan, pero el problema con su respuesta es que no evita que alguien pueda pegar en un texto largo. El siguiente va a impedir que un usuario de pegar en cosas para eludir el límite:

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

    Esto impedirá que una de las teclas se pulsen si la longitud no es el pase de max, pero si pasa a max, simplemente reemplace la cadena en el área de texto con una cadena más corta. El text variable es el JTextArea swing objeto.

    • Parece que esta línea: «else if(texto.getText().longitud() > max)» debe decir: «else if(texto.getText().longitud() >= max)»

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein