Null Pointer Exception bei Focus Event bei einem JTextField

Lit-Web

Aktives Mitglied
Hallo Leute,

ich glaube ich habe eine Ahnung wo der Fehler her rührt, aber wie ich es anders lösen kann will mir grad keine Idee in den Kopf.

Ich will bei einer Loginkontrolle folgendes erreichen, wenn nach der Eingabe des Passworts das Feld verlassen wird soll der Button zum Login erscheinen.

Ich bekomme folgende Exception geworfen wenn der Event ausgelöst wurde.

Code:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at TextFieldFocusAction.focusLost(TextFieldFocusAction.java:29)
	at java.awt.AWTEventMulticaster.focusLost(Unknown Source)
	at java.awt.Component.processFocusEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
	at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
	at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

Hier meine GUI.
Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

public class LoginGuiElement extends JPanel {
	
	protected JLabel lblLogName;
	protected JLabel lblPwd;
	protected GridBagLayout pnlLoginLayout;
	protected JTextField loginNameField;
	protected JTextField loginPwdField;
	protected JButton loginButton;
	protected ArrayList<String> fieldValues;
	
	/**
	 * 
	 * Konstruktor gibt das fertige Panel mit allen Loginelementen zurück
	 * 
	 * */
	public LoginGuiElement () {
		this.setSize( 500, 500 );
		this.setLayout( this.createLogPanelLayout() );
		this.setPreferredSize( new Dimension( 500, 150 ) );
		this.setBackground( Color.white );
		this.setVisible( true );
		this.add( this.returnLblLogName() );
		this.add( this.returnLblPwd() );
		this.add( this.returnNameField() );
		this.add( this.returnPwdField() );
		this.add( this.returnBtnLogin() );
		fieldValues = new ArrayList<String>();
		fieldValues.add( this.returnNameField().getText() );
		fieldValues.add( this.returnPwdField().getText() );
	}
	
	/**
	 * 
	 * Label Loginname
	 * 
	 * */
	protected JLabel returnLblLogName () {
		lblLogName = new JLabel();
		Font f = new Font( "Arial", Font.BOLD, 12 );
		lblLogName.setText( "Loginname" );
		lblLogName.setSize( 120, 20 );
		lblLogName.setFont( f );
		lblLogName.setForeground( Color.black );
		lblLogName.setLocation( 10, 40 );
		lblLogName.setVisible( true );
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.gridwidth = 1;
		gbc.gridheight = 1;
		gbc.weightx = 100;
		gbc.weighty = 20;
		pnlLoginLayout.setConstraints( lblLogName, gbc );
		return lblLogName;
	}
	
	/**
	 * 
	 * Label Passwortext
	 * 
	 * */
	protected JLabel returnLblPwd () {
		lblPwd = new JLabel();
		Font f = new Font( "Arial", Font.BOLD, 12 );
		lblPwd.setText( "Passwort" );
		lblPwd.setSize( 120, 20 );
		lblPwd.setFont( f );
		lblPwd.setForeground( Color.black );
		lblPwd.setLocation( 10, 40 );
		lblPwd.setVisible( true );
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.gridx = 0;
		gbc.gridy = 1;
		gbc.gridwidth = 1;
		gbc.gridheight = 1;
		gbc.weightx = 100;
		gbc.weighty = 20;
		pnlLoginLayout.setConstraints( lblPwd, gbc );
		return lblPwd;
	}
	
	/**
	 * 
	 * Eingabefeld für den Loginnamen
	 * 
	 * */
	protected JTextField returnNameField () {
		loginNameField = new JTextField();
		loginNameField.setPreferredSize( new Dimension( 120, 20 ) );
		loginNameField.setVisible( true );
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.gridx = 1;
		gbc.gridy = 0;
		gbc.gridwidth = 1;
		gbc.gridheight = 1;
		gbc.weightx = 120;
		gbc.weighty = 20;
		pnlLoginLayout.setConstraints( loginNameField, gbc );
		return loginNameField;
	}
	
	/**
	 * 
	 * Eingabefeld für die Passworteingabe
	 * von hier aus soll der Focus Event ausgelöst werden wenn der Focus des Feldes verlassen wird
	 * 
	 * */
	protected JTextField returnPwdField () {
		loginPwdField = new JTextField();
		loginPwdField.setPreferredSize( new Dimension( 120, 20 ) );
		loginPwdField.addFocusListener( new TextFieldFocusAction( fieldValues ,loginButton ) );
		loginPwdField.setVisible( true );
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.gridx = 1;
		gbc.gridy = 1;
		gbc.gridwidth = 1;
		gbc.gridheight = 1;
		gbc.weightx = 120;
		gbc.weighty = 20;
		pnlLoginLayout.setConstraints( loginPwdField, gbc );
		return loginPwdField;
	}
		
	/**
	 * 
	 * Login Button der einen Event feuert um sich ins System einzuloggen
	 * 
	 * */
	protected JButton returnBtnLogin () {
		loginButton = new JButton();
		loginButton.setPreferredSize( new Dimension( 120, 20 ) );
		loginButton.setText( "Login" );
		loginButton.setVisible( false );
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.gridx = 1;
		gbc.gridy = 2;
		gbc.gridwidth = 1;
		gbc.gridheight = 1;
		gbc.weightx = 120;
		gbc.weighty = 20;
		pnlLoginLayout.setConstraints( loginButton, gbc );
		return loginButton;
	}
	
	/**
	 * 
	 * Layoutmanger wird ans Panel übergeben
	 * 
	 * */
	protected GridBagLayout createLogPanelLayout () {
		pnlLoginLayout = new GridBagLayout();
		return pnlLoginLayout;
	}
}

Und hier meine ausgelagerte Focus Action
Java:
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.ArrayList;
import javax.swing.*;

public class TextFieldFocusAction implements FocusListener {
	
	protected JButton btnLogin;
	protected ArrayList<String> values;
	
	public TextFieldFocusAction ( ArrayList<String> pFieldValues, JButton pBtnLogin ) {
		values = new ArrayList<String>();
		values = pFieldValues;
		btnLogin = pBtnLogin;
	}
	
	public void focusLost ( FocusEvent txtFocusEvent ) {
		
		if ( !values.get(0).equals("") && !values.get(1).equals("") ) {
			btnLogin.setVisible( true );
		}
	}
	
	public void focusGained ( FocusEvent pFocusEvent ) {
		
	}
}

Ich habe nun gesucht und gesucht, aber wirklich etwas finden was auf das Problem zutrifft konnte ich nicht. Ich vermute das der Fehler in GUI Klasse in Zeile 116 der Auslöser ist. Wie kann ich das anders machen?

Vielen Dank für Hilfe und Antwort.

Mfg Lit-Web
 
tja, deine Nennung der Zeil 116 lässt vermuten dass du erkannt hast, dass dort der übergebene Button noch null ist
auch wenn es noch schlauer klänge, wenn du das direkt gesagt hättest

- du könntest auf eine richtige Initialisierungsreihenfolge achten, die Methode returnBtnLogin() vor returnPwdField() aufrufen,
aber das ist nur eine temporäre Heilung, Fehler sind weiter möglich
- du könntest die Variablen gleich mit [c]JButton loginButton = new JButton();[/c]
initialisieren, dann hast du aber Probleme, diese später noch richtig zu initialisieren, wird auch nicht schön,
- falls du den zuletzt genannten Weg nicht gehst solltest du dir gleich für das komplette Programm merken: nie auf die Instanzattribute direkt zugreifen, nur über die Methoden,
und diese dann nach dem Schema bauen
Java:
getButtonX() {
if (this.x != null) { return this.x; }
this.x = ..;
..
}
ganz sicher muss das auch nicht unbedingt sein, etwa wenn getButtonX() getButtonY() benötigt und y wieder x
 
Hallo,

weil loginButton erst in Zeile 31 von LoginGuiElement initialisiert wird (indirekt über returnBtnLogin()), ist die Variable in der zuvor in Zeile 30 aufgerufenen Methode returnPwdField() natürlich noch null.
Schnelle Lösung: Zeile 30 und 31 vertauschen
Saubere Lösung: Lazy initialization - Wikipedia, the free encyclopedia bei den returnBtn/PwdField/usw()-Methoden einsetzen und dann
Java:
loginPwdField.addFocusListener( new TextFieldFocusAction( fieldValues ,returnBtnLogin() ) );
statt
Java:
loginPwdField.addFocusListener( new TextFieldFocusAction( fieldValues ,loginButton ) );
verwenden.
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben