Porządny TextField (min, max wartość, walidacja, typ, ikonka, menu)

0

Witam, próbuję napisać TextField'a z kilkoma funkcjami, wcześniej pisałem w C# i zrobienie identycznego kodu zajęło mi kilka chwil...
Początki w javie nie są jednak tak łatwe i przyjemne. Przede wszystkim mój TextField ma posiadać wartości określające min i max długości pola. W przypadku gdy podjęto próbę edycji pola, a nie zostało osiągnięta min wartość obramowanie zmienia się, i to działa, ale nie do końca. W przypadku gdy mamy jeden znak i usuniemy go to zdarzenie zostanie wywołane, ale wartość pola nie została jeszcze zaktualizowana, przez co metoda widzi długość pola 1, i nie zmienia obramowania na początkową... Jakim zdarzeniem mam przechwycić zmianę wartości pola? Przypuszczam, że przepisanie tam tego kodu, da zamierzony efekt.
Dalej co do max długości pola, obramowanie zmienia się, ale nie wiem w jaki sposób zablokować długość tak, żeby nie było możliwości wpisania dalszego tekstu lub wklejenia go. Kolejną rzeczą jakie TextField ma spełniać to walidacja, w przypadku zakończenia pracy na polu lub potwierdzenia enterem. Co do potwierdzenia to wystarczy TextFieldLimitsActionPerformed, ale co z zakończeniem pracy czyli użyciem Tab lub po prostu wybranie kursorem innego pola. Następnie TextField docelowo ma pozwalać na wprowadzanie określonych typów danych, czyli tylko cyfry, kwota, tekst bez spacji itp. Przypuszczam, że do tego wystarczy wykorzystać TextFieldLimitsKeyPressed, ale czy Java udostępnia sprawdzenie znaku np. isDigit? Jak przeciążyć metodę Print o ile tak ona się nazywa, aby była możliwość dodania ikony przed lub za TextField? Ostatnią, rzeczą jest podpięcie menu z opcjami kopiuj, wklej, wytnij. Chciałbym aby odpowiednie opcje dostępne były tylko jeżeli dana operacja jest możliwa, czyli jeżeli TextField jest pusty to nie można kopiować czy wyciąć. Tylko które zdarzenie obsługuję przygotowanie menu przed wyświetleniem? Co do kopiuj to z kąd w Javie pobrać to co jest w pamięci? Bo wiadomo w pamięci może być jednocześnie grafika i tekst, a nam zależy na wklejeniu tekstu.

public class TextFieldLimits extends JTextField
{
    private int iMinLenght = - 1;
    private int iMaxLenght = - 1;
    private Border oBorder = getBorder();
    private String szInitialToolTip = null;

    protected enum ConfigParamStatus
    {
        MIN_LENGHT, MAX_LENGHT
    };

    public TextFieldLimits()
    {
        super();
        
        this.addKeyListener(new KeyAdapter()
        {
            @Override
            public void keyPressed(java.awt.event.KeyEvent evt)
            {
                TextFieldLimitsKeyPressed(evt);
            }
        });

        this.addActionListener(new java.awt.event.ActionListener()
        {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                TextFieldLimitsActionPerformed(evt);
            }
        });
    }

    public TextFieldLimits(ConfigParamStatus status, int values)
    {
        this();

        if (values > 0)
        {
            switch (status)
            {
                case MIN_LENGHT:
                    this.iMinLenght = values;
                    break;
                case MAX_LENGHT:
                    this.iMaxLenght = values;
                    break;
            }
        }
    }

    public TextFieldLimits(int iMinLenght, int iMaxLenght)
    {
        this();

        if (iMinLenght > 0)
        {
            this.iMinLenght = iMinLenght;
        }

        if (iMaxLenght > 0 && iMaxLenght >= iMinLenght)
        {
            this.iMaxLenght = iMaxLenght;
        }
    }

    private void TextFieldLimitsKeyPressed(KeyEvent evt)
    {
        setBorder(oBorder);
        setToolTipText(szInitialToolTip);
        
        if (this.iMinLenght > 0)
            if (iMinLenght > getText().length())
            {
                setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.RED));
                szInitialToolTip = getToolTipText();
                setToolTipText("The maximum field length");
            }
        
        if (iMaxLenght <= getText().length())
        {
            setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.ORANGE));
            szInitialToolTip = getToolTipText();
            setToolTipText("The minimum field length is not reached");
        }
    }

    private void TextFieldLimitsActionPerformed(ActionEvent evt)
    {
        boolean validing = validing();
    }
    
    public boolean setMaxLenght(int iMaxLenght)
    {
        boolean set = false;

        if (iMaxLenght > 0 && iMaxLenght >= this.iMinLenght)
        {
            this.iMaxLenght = iMaxLenght;
            set = true;
        }

        return set;
    }

    public boolean setMinLenght(int iMinLenght)
    {
        boolean set = false;

        if (iMinLenght > 0 && (iMinLenght <= this.iMaxLenght) || !(this.iMaxLenght > 0))
        {
            this.iMinLenght = iMinLenght;
            set = true;
        }

        return set;
    }

    public int getMaxLenght()
    {
        return this.iMaxLenght;
    }

    public int getMinLenght()
    {
        return this.iMinLenght;
    }

    public boolean validing()
    {
        boolean bVal = false;

        //if()

        return bVal;
    }
}
0

A ja Ci powiem że to wszystko zostało już zrobione. Była kiedyś taka jarka ogólnie z netbeansa która załatwiała właśnie sprawy walidacji, min, max, zakresy itp. Tylko cholera już jej nie mam na hdd...a nazwa mi umknęła. Ktoś kojarzy bo też teraz coś takiego potrzebuje.

0

Napisałem kiedyś własne klasy JInputInteger i JInputDouble z dopuszczalnym zakresem, walidacją, sygnalizacją błędu, niemożliwością zdjęcia fokusu gdy dane niepoprawne. Mogę Ci udostępnić.

0

Mnie możesz udostępnić - będe wdzięczny.

0

Nie umiem z forum wysłać maila z załącznikiem.

0

Podzielę się tym co mam licząc na to, że podpowiecie dalej co zrobić żeby osiągnąć cel i poradzicie jak poprawić błędy które znajdziecie ;)
Na chwilę obecną mam tyle.
Czyli użytkownik może określić max i min dla pola, jeżeli nie jest to spełniane to jest zmiana obramowania + ikonka na końcu.
I tu leży pierwszy problem. Jeżeli określę max większy od długości pola które może obsłużyć dany limit, to pod ikonką znajdzie się tekst.
Pierwsze pytanie to w jaki sposób mogę zmusić pole do tego aby pod ikonką nie znalazł się tekst. Dodatkowo chciałem dodać ikonkę obrazującą przeznaczenie pola, czyli np. przy loginie znalazła by się ikonka osoby i klucza, dla adres jakiś domek itp. Tylko w jaki sposób mogę rysować poza obszarem pola? Albo ja coś przeoczyłem i jest to banalnie proste? Brakuje jeszcze menu z opcjami wklej, wytnij i kopiuj, ale to może w kolejnej wersji. A co do tego co jeszcze może klasa to na koniec walidacja pola z sprawdzenie czy w przypadku braku zgodności z minimum umożliwić przejście dalej lub wymusić poprawność danych. Chciałbym zapytać jak w javie wymusić format danych podczas walidacji czyli dla maila [email protected], lub aktywnie podczas wpisywania np. kodu dodać - pomiędzy znakami 2, a 3?

/**
 * @author Robert Troska [email protected]
 * @description TextFieldLimits class inherits from JTextField
 * Support for field length along with text messages and icon,
 * control input characters, field validation.
 */
public class TextFieldLimits extends JTextField implements DocumentListener
{

    /** Values ​​for the length of the field (min and max)
     * 0 means the value of indeterminate */
    private int iMinLenght = 0;
    private int iMaxLenght = 0;
    /** Value specifies the acceptable character to the field
     * FULL_TEXT means lack of control input characters */
    private ParamTextFieldLimits ParamTextFieldLimits;
    /** Vars icons on the field */
    private BufferedImage imgIcon = null;
    private BufferedImage imgIconError = null;
    /** Original values border and toolTipText */
    private Border oBorder = getBorder();
    private String szInitialToolTip = null;
    /** Value that specifies you can change the field when wrong field verification
     * option is disabled default */
    private boolean bLockVerification = false;

    /** Values ​​to determine the Min and Max */
    public static enum ParamLenght
    {
          MIN_LENGHT, MAX_LENGHT
    };
    
    public static enum ParamTextFieldLimits
    {
        FULL_TEXT, DIGIT, MONEY, LETTER
    };

    /** The paint method icons field */
    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        if (imgIconError != null)
        {
            try
            {
                Border border = UIManager.getBorder("TextField.border");
                final int x = getWidth() - border.getBorderInsets(this).right - imgIconError.getWidth() - 4;
                int y = (getHeight() - imgIconError.getHeight()) / 2;
                g.drawImage(imgIconError, x, y, this);
            }
            catch (Exception ignore)
            {
            }
        }
    }

    @Override
    public void insertUpdate(DocumentEvent event)
    {
        changedDocment(event, "insert");
    }

    @Override
    public void removeUpdate(DocumentEvent event)
    {
        changedDocment(event, "remove");
    }

    @Override
    public void changedUpdate(DocumentEvent event)
    {
        changedDocment(event, "update");
    }

    /** Description of changedDocment(DocumentEvent evt, String option)
     * Method responsible for checking the max and min length of the field
     *
     * @param DocumentEvent evt is event
     * @param String option is name of the event that triggered the method
     * @return void
     */
    private void changedDocment(DocumentEvent evt, String option)
    {
        imgIconError = null;

        if (oBorder != getBorder())
        {
            setBorder(oBorder);
        }

        if (szInitialToolTip != getToolTipText())
        {
            setToolTipText(szInitialToolTip);
        }

        executeMinLength();
        executeMaxLength();
    }

     /** Description of textFieldLimitsVerification()
     * Method verifying the correctness of the field
     *
     * @return boolean values true for compliance field
     */
    private boolean textFieldLimitsVerification()
    {
        boolean isGood = true;

        if (isMinLenght())
        {
            if (checktMinLength())
            {
                executeMinLength();
                isGood = false;
            }
        }

        return isGood;
    }
            
    /** Description of verification
     * Class responsible for field verification
     */
    class verification extends InputVerifier
    {
        /** Description of verify(JComponent input)
         * Method responsible for checking the max and min length of the field
         *
         * @param indication of the validated component
         * @return boolean value determines the possibility of move to other fields
         */
        @Override
        public boolean verify(JComponent input)
        {
            boolean isGood = textFieldLimitsVerification();

            if (isGood)
            {   
                setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.GREEN));

                setIconError("/ispman/component/resources/img/16_accept.png");
            }

            if (bLockVerification)
                return isGood;
            else
                return true;
            
        }
    }
    
    /** Description of textFieldLimitsKeyReleased(KeyEvent evt)
     * Method supports the release of key
     * for too long the text is truncated in length max
     * 
     * @param KeyEvent 
     * @return void
     */
    private void textFieldLimitsKeyReleased(KeyEvent evt)
    {
        if(isMaxLenght())
            if (getText().length() > iMaxLenght)
            {
                SwingUtilities.invokeLater(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        setText(getText().substring(0, iMaxLenght));
                    }
                });
            }
    }
    
    /** Description of textFieldLimitsKeyTyped(KeyEvent evt)
     * Method supports the typed of key
     * allows you to enter only a specific type of data
     * additional data for too long interrupt event handler
     * 
     * @param KeyEvent 
     * @return void
     */
    private void textFieldLimitsKeyTyped(KeyEvent evt)
    {
        char c = evt.getKeyChar();

        if (isMaxLenght())
        {
            if (getText().length() >= iMaxLenght)
            {
                evt.consume();
            }
        }

        if (ParamTextFieldLimits != null)
        {
            switch (ParamTextFieldLimits)
            {
                case FULL_TEXT:
                    break;
                case DIGIT:
                    if (!Character.isDigit(c))
                    {
                        evt.consume();
                    }
                    break;
                case LETTER:
                    if (!Character.isLetter(c))
                    {
                        evt.consume();
                    }
                    break;
            }
        }
    }

    public TextFieldLimits()
    {
        super();

        setInputVerifier(new verification());
        getDocument().addDocumentListener(this);

        addKeyListener(new KeyAdapter()
        {

            @Override
            public void keyTyped(KeyEvent evt)
            {
                textFieldLimitsKeyTyped(evt);
            }

            @Override
            public void keyReleased(KeyEvent evt)
            {
                textFieldLimitsKeyReleased(evt);
            }

            @Override
            public void keyPressed(KeyEvent evt)
            {
            }
        });
    }

    public TextFieldLimits(ParamLenght status, int values)
    {
        this();

        if (values > 0)
        {
            switch (status)
            {
                case MIN_LENGHT:
                    this.iMinLenght = values;
                    break;
                case MAX_LENGHT:
                    this.iMaxLenght = values;
                    break;
            }
        }
    }

    public TextFieldLimits(int iMinLenght, int iMaxLenght)
    {
        this();

        if (iMinLenght > 0)
        {
            this.iMinLenght = iMinLenght;
        }

        if (iMaxLenght > 0 && iMaxLenght >= iMinLenght)
        {
            this.iMaxLenght = iMaxLenght;
        }
    }

    public boolean setMaxLenght(int iMaxLenght)
    {
        boolean set = false;

        if (iMaxLenght > 0 && iMaxLenght >= this.iMinLenght)
        {
            this.iMaxLenght = iMaxLenght;
            set = true;
        }

        return set;
    }

    public int getMaxLenght()
    {
        return this.iMaxLenght;
    }

    public boolean isMaxLenght()
    {
        if (iMaxLenght > 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public boolean setMinLenght(int iMinLenght)
    {
        boolean set = false;

        if (iMinLenght > 0 && (iMinLenght <= this.iMaxLenght) || !(this.iMaxLenght > 0))
        {
            this.iMinLenght = iMinLenght;
            set = true;
        }

        return set;
    }

    public int getMinLenght()
    {
        return this.iMinLenght;
    }

    public boolean isMinLenght()
    {
        if (iMinLenght > 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public void setParamTextFieldLimits(ParamTextFieldLimits param)
    {
        this.ParamTextFieldLimits = param;
    }

    public ParamTextFieldLimits getParamTextFieldLimits()
    {
        return ParamTextFieldLimits;
    }

    public void setIcon(BufferedImage image)
    {
        this.imgIcon = image;
    }

    public BufferedImage getIcon()
    {
        return this.imgIcon;
    }

    public void setLockVerification(boolean bLockVerification)
    {
        this.bLockVerification = bLockVerification;
    }

    public boolean getLockVerification()
    {
        return bLockVerification;
    }

    private boolean checktMinLength()
    {
        boolean isMin = false;

        if (isMinLenght())
        {
            if (iMinLenght > getText().length())
            {
                isMin = true;
            }
        }

        return isMin;
    }

    private boolean checktMaxLength()
    {
        boolean isMax = false;

        if (isMaxLenght())
        {
            if (iMaxLenght < getText().length())
            {
                isMax = true;
            }
        }

        return isMax;
    }

    // ADD LOGER !!
    private void setIconError(String url)
    {
        try
        {
            imgIconError = (ImageIO.read(this.getClass().getResource(url)));
        }
        catch (IOException ex)
        {
        }
    }

    private void executeMinLength()
    {
        if (checktMinLength() && getText().length() > 0)
        {
            oBorder = getBorder();
            setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.RED));

            szInitialToolTip = getToolTipText();
            setToolTipText("The minimum field length is not reached");

            setIconError("/ispman/component/resources/img/16_delete.png");
        }
    }

    private void executeMaxLength()
    {
        if (checktMaxLength())
        {
            setText(getText().substring(0, iMaxLenght));
        }

        if (iMaxLenght == getText().length())
        {
            oBorder = getBorder();
            setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.ORANGE));

            szInitialToolTip = getToolTipText();
            setToolTipText("The maximum field length");

            setIconError("/ispman/component/resources/img/16_error.png");
        }
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1