Ich hab eine kleine Anwendung geschrieben, ein Thread, der jede minute die Uhrzeit aktualisiert.
Es funktioniert auch jedoch wirft der Compiler immer eine NullPointerException, ob wohl es geht.
Ich kenne mich mit Threads nicht so aus, daher wollte ich mal woran es liegen kann?
Und eventuell wäre noch interessant ob einer mir ein Hinweis geben könnte wie ich ein Timer einbauen kann, der 5 min runterläuft.
für den fall dass es hilft, ist hier mein code:
public class ThreadClockTest extends Thread {
String text;
public ThreadClockTest() {
}
public void run() {
while (!this.isInterrupted()) {
Platform.runLater(new Runnable() {
@Override
public void run() {
SimpleDateFormat c = new SimpleDateFormat("HH:mm");
Date date = new Date();
Instant s = Instant.parse("2015-12-31T00:00:00Z");
Instant myClock = Instant.now();
clockLable.setText(c.format(date));
int min=5;
int sec=60;
for (int i = 0; i < 10; i++) {
clockMin.setText(""+min);
clockSec.setText(""+sec);
if (sec==0) {
min--;
sec=60;
}if (min==0) {
clockMin.setText("0");
clockSec.setText("0");
}
}
}
});
try {
sleep(TimeUnit.SECONDS.toMillis(60));
System.out.println("its work");
}
catch(InterruptedException e) {
System.out.println("error");
}
}
}
}
Exception in thread “JavaFX Application Thread” java.lang.NullPointerException
at application.GuiController$ThreadClockTest$1.run(GuiController.java:254)
at com.sun.javafx.application.PlatformImpl.lambda$null$164(PlatformImpl.java:292)
at com.sun.javafx.application.PlatformImpl$$Lambda$48/791815167.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$165(PlatformImpl.java:291)
at com.sun.javafx.application.PlatformImpl$$Lambda$47/1775282465.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
Zeile 254 aus GuiController ist offensichtlich von Belang,
diese Information aus StackTrace zu lesen noch nicht bekannt?
wenn doch dann recht ärgerlich hier nicht zu nennen, welche Zeile denn 254 ist…,
oftmals geht es auch so, hier zumindest für mich nicht direkt ersichtlich,
vielleicht clockMin/ clockSec null,
die Schleife dort scheint eh nicht recht nützlich ohne sleep darin, was bei runLater() auch nicht zu empfehlen ist,
EINE Schleife, gewiss im Thread (oder Timer), zu jedem Durchlauf die Zeit bestimmen,
Differenz etwa zu am Anfang gemerkter Startzeit, und Felder aktualisieren
Tut mir echt leid, die Zeile 254 ist in diesem fall (oben im Code, die Zeile 21: clockLable.setText(c.format(date));).
Der NullPointer wird immer da geworfen, wo ich den Text auf die GUI übergebe(z.B kommentiere ich diese Zeile aus, so wird der Exception auf den nächsten Label geworfen, aber irgendwie muss ich ja Text ausgeben können).
Das mit der Schleife war mir so nicht bekannt, danke dir und danke ich für den Link.
Ja nun, dann ist clockLable eben null - aber wo das deklariert wird (oder einen Wert erhält, der nicht null ist), erkennt man am geposteten Code nicht…
Nun, deklariert ist sie in einer separaten FXML dabei, aus die ich mittels: “@FXML private TextField clockLable;” zugreife.
In der entsprechenden Zeile 21, wir ein Wert zugewiesen (die aktuelle Uhrzeit), daher kann sie doch nicht null sein, oder verstehe ich das falsch?
setze eine System.out.println()-Ausgabe davor, um zu prüfen ob null oder nicht,
alles andere ist weniger relevant, wenn auch nicht außer Acht zu lassen,
genauso deine Aussage ‘es funktioniert’ am Anfang, also clockLable zu sehen?
möglich ist noch, dass du mehrere Objekte derselben Klasse hast, Vererbung, mehrere Threads laufen,
manche funktionieren und werden angezeigt, andere nicht vollständig initialisiert usw.,
während ein Thread mit Fehler abbricht sorgt ein anderer für gute Anzeige
poste evtl. vollständiges Programm, baue viele System.out.println() ein mit Ausgaben der Hashcode der Objekte,
System.out.println() in Konstruktoren wichtiger eigener Klassen wie GUI-Objekte oder Threads ist effektiv
Hmja, wie genau das mit @FXML so unter der Haube abläuft weiß ich (leider, immer noch) nicht genau, aber ich denke, ein wichtiger Punkt ist das, was SlaterB angesprochen hat: Siehst du das Label?
Eine Vermutung: Das ganze läuft irgendwie los, aber das dort erstellte Runnable wird (mindestens) einmal ausgeführt, bevor dieses Label tatsächlich “injected” wurde - d.h. beim ersten Aufruf ist es noch null. Das ist wild geraten, würde aber zumindest die Symptome (soweit verständlich beschrieben) erklären.
@FXML private TextField clockLable; bringt einem nicht viel wenn man in der .fxml nicht die ID für die Komponente gesetzt hat. Wenn du das im SceneBuilder machst, müsste unter ‘Code’ auf der rechten Seite ein Feld namens ‘fx:id’ sein. Da dann ‘clockLable’ reinschreiben. Mir fällt gerade auf, dass du ‘clockLable’ anstatt ‘clockLabel’ geschrieben hast. Vielleicht ein typo?