Java >> Java-zelfstudie >  >> Java

Verander de achtergrondkleur bij het typen van een bepaalde waarde (jNumberField)

Ik probeer de achtergrondkleur van een nummerveld te veranderen op basis van de cijfers die zijn ingetypt. Net zoals een nummerveld rood wordt als je er een letter in typt. Ik wil dat het ook rood wordt als je cijfers onder de 1 en hoger typt. Ik begrijp dat je dit met een knop kunt doen, maar ik wil dat het verandert als je typt.

Dit is mijn code:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class applet03 extends JApplet {
  private JButton bHoeveelheid = new JButton();
  private JNumberField nfAantal = new JNumberField();  
  private JTextArea taLijst = new JTextArea("");
    private JScrollPane taLijstScrollPane = new JScrollPane(taLijst);
 public void init() {
    Container cp = getContentPane();
    cp.setLayout(null);
    cp.setBounds(0, 0, 442, 478);
    bHoeveelheid.setBounds(224, 56, 59, 33);
    bHoeveelheid.setMargin(new Insets(2, 2, 2, 2));
    bHoeveelheid.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
        bHoeveelheid_ActionPerformed(evt);
      }
    });
    cp.add(bHoeveelheid);
    nfAantal.setBounds(304, 56, 99, 36);
    nfAantal.setText("Vul getal in");
    nfAantal.setHorizontalAlignment(SwingConstants.CENTER);
    nfAantal.addFocusListener(new FocusAdapter() { 
      public void focusGained(FocusEvent evt) { 
        nfAantal_FocusGained(evt);
      }
    });
    nfAantal.addKeyListener(new KeyAdapter() { 
      public void keyPressed(KeyEvent evt) { 
        nfAantal_KeyPressed(evt);
      }
    });
    cp.add(nfAantal);
    taLijstScrollPane.setBounds(224, 136, 168, 180);
    cp.add(taLijstScrollPane);
  }
  public void bHoeveelheid_ActionPerformed(ActionEvent evt) {    
    if (nfAantal.getInt() < 1 || nfAantal.getInt() > 7) {
      nfAantal.setBackground(Color.RED);
    } else {
      //some other code (not impotant for now)
      }
  }  
  public void nfAantal_FocusGained(FocusEvent evt) {    
    if (nfAantal.getText().equals("Vul getal in")) {
      nfAantal.clear();
    }
  }  
  public void nfAantal_KeyPressed(KeyEvent evt) {
    if (nfAantal.getInt() < 1 || nfAantal.getInt() > 7) {
      nfAantal.setBackground(Color.RED);
    } else {
      //some other code (not impotant for now)
      }
  }  
}

Het knopgedeelte werkt, maar de KeyEvent niet. En als ik dit uitvoer, krijg ik steeds deze fouten:

Exception in thread "AWT-EventQueue-1" java.lang.NumberFormatException: empty String

Maar als ik dit doe, werkt het wel. Ik krijg nog steeds dezelfde fouten, maar het werkt. (Trouwens, niet optimaal, omdat het het alleen bij elke tweede toetsaanslag aan het tekstveld toevoegt.):

  public void nfAantal_KeyPressed(KeyEvent evt) {
    if (nfAantal.getInt() < 1 || nfAantal.getInt() > 7) {
      taLijst.append(nfAantal.getText());
    } else {
      //some other code (not impotant for now)
      }
  }  

Dus als iemand weet waarom dit niet werkt of een betere manier weet om dit te bereiken. Dan wordt dat zeer op prijs gesteld!

(Trouwens, ik gebruik Java 1.8)

Bewerken:

Ik heb nu (nfAantal.getText().length() > 0) && (nfAantal.getInt() < 1 || nfAantal.getInt() > 7) in de if-statement en dat deed de fouten verdwijnen. (Met dank aan @Joe)
Maar dat lost nog steeds mijn vraag niet op over hoe je de achtergrond rood kunt maken op bepaalde waarden.

Aanvullende informatie over JNumberField :

Ik denk dat deze link de code bevat waaruit JNumberField bestaat en deze link bevat een download naar het .jar-bestand met daarin de JNumberField Java-bestand.

Nog een bewerking:

Ik denk dat ik er zelf achter ben gekomen waarom het niet werkt met een JNumberfield; in de code verandert het de achtergrond in wit als de waarde numeriek is, dus alleen als er een manier is om dit deel van de code te omzeilen of het te veranderen (wat ik niet weet hoe ik dat moet doen), kan mijn vraag worden beantwoord voor een JNumberField , als dit niet het geval is, gebruik ik de JFormattedTextField in plaats daarvan.

Dit is de code die moet worden gewijzigd of omzeild:

  protected void processKeyEvent(KeyEvent e) {
    super.processKeyEvent(e);
    if (isNumeric() || getText().equals("-") ||
        getText().equals("") || getText().equals("."))
      setBackground(Color.white);
    else
      setBackground(Color.red);
  }

Antwoord

Ik weet niet wat een JNumberField is. Het maakt geen deel uit van de JDK en toen ik met Google zocht, werden er verschillende gevonden.

Ik begrijp ook niet waarom je een applet schrijft .

Daarom is de onderstaande code mogelijk niet geschikt omdat het een op zichzelf staande Swing is applicatie die gebruikmaakt van JFormattedTextField en DocumentListener.

Uitleg achter de code.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.text.NumberFormat;

import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.NumberFormatter;

public class RedNumbr implements DocumentListener, Runnable {
    private JFormattedTextField  aantal;
    private JFrame  frame;

    @Override
    public void insertUpdate(DocumentEvent event) {
        handleDocumentEvent(event);
    }

    @Override
    public void removeUpdate(DocumentEvent event) {
        handleDocumentEvent(event);
    }

    @Override
    public void changedUpdate(DocumentEvent event) {
        // Never called for 'JFormattedTextField'
    }

    @Override
    public void run() {
        showGui();
    }

    private JPanel createNumberPanel() {
        JPanel numberPanel = new JPanel();
        NumberFormat format = NumberFormat.getIntegerInstance();
        NumberFormatter formatter = new NumberFormatter(format);
        aantal = new JFormattedTextField(formatter);
        aantal.setColumns(10);
        Document doc = aantal.getDocument();
        doc.addDocumentListener(this);
        numberPanel.add(aantal);
        return numberPanel;
    }

    private void handleDocumentEvent(DocumentEvent event) {
        Document doc = event.getDocument();
        int len = doc.getLength();
        if (len > 0) {
            try {
                String text = doc.getText(0, len);
                int number = Integer.parseInt(text);
                Color fg;
                if (number < 1  ||  number > 7) {
                    fg = Color.red;
                }
                else {
                    fg = UIManager.getColor("TextField.foreground");
                }
                aantal.setForeground(fg);
            }
            catch (BadLocationException | NumberFormatException x) {
                // Ignore.
            }
        }
    }

    private void showGui() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(createNumberPanel(), BorderLayout.CENTER);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new RedNumbr());
    }
}

Wanneer de inhoud van de JFormattedTextField zijn gewijzigd, de relevante DocumentListener methode wordt ingeroepen. Bij die methodes controleer ik of de JFormattedTextField bevat een nummer en als dat zo is, verander ik de voorgrondkleur van de JFormattedTextField volgens uw voorwaarden, d.w.z. als het getal kleiner is dan één (1) of groter dan 7 (zeven).

Merk op dat de NumberFormatter verhindert het invoeren van niet-cijfers niet omdat JFormattedTextField handelt dat af wanneer het de focus verliest. Desalniettemin verwerkt het het invoeren van positieve en negatieve getallen, wat u wat werk bespaart. En het punt van mijn antwoord is gewoon om te laten zien hoe je de voorgrondkleur kunt veranderen op basis van de ingevoerde tekst, die volgens mij je vraag beantwoordt.

BEWERKEN

Om de achtergrond van de JFormattedTextField . te veranderen , in plaats van de voorgrond, hoef je alleen maar twee regels in mijn bovenstaande code te wijzigen.

Vervang

fg = UIManager.getColor("TextField.foreground");

met

fg = UIManager.getColor("TextField.background");

en ook vervangen

aantal.setForeground(fg);

met

aantal.setBackground(fg);

Java-tag