Hallo,
ich versuche einen Custom-Button mit einem Custom-Controller zu erstellen. Die Custom-Komponente wird bereits im Application-Window angezeigt, aber ich hab einige Probleme mit den Properties.
Projekt Struktur:
[CODE lang="java" title="Custom-Controller"]package controller;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import java.net.URL;
import java.util.ResourceBundle;
public class TopBarBtn implements Initializable {
public ImageView getIv() {
return iv;
}
public HBox getHbox() {
return hbox;
}
@FXML private ImageView iv;
@FXML private HBox hbox;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
}[/CODE]
Custom-Komponente (TopBarCloseBtn.class):
[CODE lang="java" title="Custom-Komponente (TopBarCloseBtn.class):"]package custom;
import controller.TopBarBtn;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.layout.HBox;
import java.io.IOException;
public class TopBarCloseBtn extends HBox {
TopBarBtn controller;
private final StringProperty imageUrl = new SimpleStringProperty("/res/image/white/closeX.png");
public final StringProperty imageUrl() { return imageUrl; }
public final String getImageUrl() { return imageUrl.get(); }
public final void setImageUrl(String imageUrl) {
this.imageUrl.set(imageUrl);
controller.getIv().setImage(new Image(imageUrl));
}
public TopBarCloseBtn() {
super();
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/res/template/closeBtn.fxml"));
controller = new TopBarBtn();
loader.setController(controller);
Node n = loader.load();
this.getChildren().add(n);
controller.getIv().setImage(new Image(imageUrl.get()));
} catch (IOException e) {
}
}
}[/CODE]
closeBtn.fxml:
[CODE lang="xml" title="closeBtn.fxml"]<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<HBox id="hbox" xmlns:fx="http://javafx.com/fxml/1" alignment="CENTER" prefHeight="27" prefWidth="40"
styleClass="TopBarButtonClose" stylesheets="@../style/TopBarButton.css">
<children>
<ImageView id="iv" fitHeight="13" fitWidth="13" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="/res/image/white/closeX.png"/>
</image>
</ImageView>
</children>
</HBox>[/CODE]
Das Problem besteht darin, dass in der Zeile controller.getIv().setImage(new Image(imageUrl.get())); in meiner Komponenten Klasse eine NullPointerException erzeugt (am Ende der komplette Fehlertext). Im Debug Modus wird mir auch angezeigt das alle Variabeln des Custom Controllers nicht initialisiert sind. Ich dachte allerdings, dass der @FXML zusatz ein Feld angibt welches durch den FXMLLoader initialisiert wird. Ich finde einfach meinen Fehler nicht. Was habe ich falsch gemacht? Gerne könnt ihr auch den restlichen Code kritisieren und paar verbesserungs Vorschläge geben, da dies meine ersten Schritte mit JavaFX sind.
MfG
Marco
ich versuche einen Custom-Button mit einem Custom-Controller zu erstellen. Die Custom-Komponente wird bereits im Application-Window angezeigt, aber ich hab einige Probleme mit den Properties.
Projekt Struktur:
- Main.class --> Zeigt das Application Window
- TopBarBtn.class --> Custom-Controller
- TopBarCloseBtn.class --> Custom-Komponente
- closeBtn.fxml --> Style für die Custom-Komponente
[CODE lang="java" title="Custom-Controller"]package controller;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import java.net.URL;
import java.util.ResourceBundle;
public class TopBarBtn implements Initializable {
public ImageView getIv() {
return iv;
}
public HBox getHbox() {
return hbox;
}
@FXML private ImageView iv;
@FXML private HBox hbox;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
}[/CODE]
Custom-Komponente (TopBarCloseBtn.class):
[CODE lang="java" title="Custom-Komponente (TopBarCloseBtn.class):"]package custom;
import controller.TopBarBtn;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.layout.HBox;
import java.io.IOException;
public class TopBarCloseBtn extends HBox {
TopBarBtn controller;
private final StringProperty imageUrl = new SimpleStringProperty("/res/image/white/closeX.png");
public final StringProperty imageUrl() { return imageUrl; }
public final String getImageUrl() { return imageUrl.get(); }
public final void setImageUrl(String imageUrl) {
this.imageUrl.set(imageUrl);
controller.getIv().setImage(new Image(imageUrl));
}
public TopBarCloseBtn() {
super();
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/res/template/closeBtn.fxml"));
controller = new TopBarBtn();
loader.setController(controller);
Node n = loader.load();
this.getChildren().add(n);
controller.getIv().setImage(new Image(imageUrl.get()));
} catch (IOException e) {
}
}
}[/CODE]
closeBtn.fxml:
[CODE lang="xml" title="closeBtn.fxml"]<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<HBox id="hbox" xmlns:fx="http://javafx.com/fxml/1" alignment="CENTER" prefHeight="27" prefWidth="40"
styleClass="TopBarButtonClose" stylesheets="@../style/TopBarButton.css">
<children>
<ImageView id="iv" fitHeight="13" fitWidth="13" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="/res/image/white/closeX.png"/>
</image>
</ImageView>
</children>
</HBox>[/CODE]
Das Problem besteht darin, dass in der Zeile controller.getIv().setImage(new Image(imageUrl.get())); in meiner Komponenten Klasse eine NullPointerException erzeugt (am Ende der komplette Fehlertext). Im Debug Modus wird mir auch angezeigt das alle Variabeln des Custom Controllers nicht initialisiert sind. Ich dachte allerdings, dass der @FXML zusatz ein Feld angibt welches durch den FXMLLoader initialisiert wird. Ich finde einfach meinen Fehler nicht. Was habe ich falsch gemacht? Gerne könnt ihr auch den restlichen Code kritisieren und paar verbesserungs Vorschläge geben, da dies meine ersten Schritte mit JavaFX sind.
MfG
Marco
Caused by: java.lang.NullPointerException: Cannot invoke "javafx.scene.image.ImageView.setImage(javafx.scene.image.Image)" because the return value of "controller.TopBarBtn.getIv()" is null at custom.TopBarCloseBtn.(TopBarCloseBtn.java:33) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:78) at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) at java.base/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:128) at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:350) at java.base/java.lang.Class.newInstance(Class.java:642) at javafx.fxml/javafx.fxml.FXMLLoader$InstanceDeclarationElement.constructValue(FXMLLoader.java:1021) at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:756) at javafx.fxml/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2808) at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2634) ... 17 more