Eine Anfrage für eine Erklärung.
Wenn die Erklärung an anderer Stelle im Internet ist, konnte ich es nicht finden. Das Problem scheint für alle Arten von benutzerdefinierten FXML-Widgets zu gelten.JavaFX - FXML: initialize() scheint keine Instanzvariablen zu erkennen
Dies ist eine erhebliche Vereinfachung eines Arbeitsprogrammmoduls. Der ursprüngliche Gedanke war, einige Instanzvariablen im benutzerdefinierten Widget-Controller zu initialisieren und zu verwenden.
Wenn die Initialisierung der Variablen im Konstruktor durchgeführt wurde, funktionierte alles gut. Die Idee, die Initialisierung vom Konstruktor in eine "initialize()" - Methode zu verschieben, erschien zu dieser Zeit gut. Hauptsächlich, wenn die Zukunft mehr Variablen enthalten könnte, die erst nach dem Ausführen des Konstruktors bis bereit sind.
Mit der "initialize()" Methode tauchte etwas auf, das ich nicht ganz verstehe wie durch den Code hier veranschaulicht.
Die Methode "initialize()" scheint Instanzvariablen nicht zu erkennen. Der Code zur Verfügung gestellt wird in funktionierender Form, das Widget erscheint und funktioniert. Das ist schlechtes Zeug ist auskommentiert nur so Leute können sehen, es funktioniert.
Wenn Sie jedoch die Methode "initialize()" auskommentieren und das Programm ausführen möchten, wird es mit einer NullPointerException für eine einfache Instanzvariable beendet. Das eigentliche Programm konnte eine HashMap nicht erkennen, aber der PrintStream hier sorgt für weniger Unordnung im gebuchten Code.
Das Problem tritt mit oder ohne @ FXML-Annotationen an allen möglichen Stellen und Kombinationen auf.
Es gibt verschiedene mögliche Gründe für den Fehler, einschließlich der folgenden.
1. "initialize()" funktioniert nicht so, wie ich es nach dem Lesen der Beschreibung glaube.
2. "initialize()" und Prozess Threads sprechen nicht miteinander?
3. Vermasselt der benutzerdefinierte Widget-Controller, der von einer Superklasse stammt, die Dinge?
4. Die Tests wurden innerhalb von NetBeans 8.0.2 mit Java 8 ausgeführt, und das vermasselt? Aber dann wird die Frage warum?
5. Anmerkungen funktionieren nicht gut mit Sub-Classing?
6. Kombinationen der oben genannten oder etwas ganz anderes?
Der Java-Code benutzerdefinierte Controller, DirectorySelectionWidgets.java:
package blogpost ;
// Java imports
import java.io .PrintStream ;
// JavaFX imports
import javafx.event .ActionEvent ;
import javafx.scene.control .Button ;
import javafx.scene.control .Control ;
import javafx.fxml .FXML ;
public class DirectorySelectionWidgets extends UserControl
{
@FXML
private Button fromRootSelectionButton ;
/**
* Does not work with or without @FXML annotation.
*/
// @FXML
protected PrintStream out = System.out ;
/**
* UNCOMMENT method to see the NullPointerException on instance variable.
* The fuller version failed on important variables.
* <P>
* Does not work with or without @FXML annotation.
*/
// @FXML
// public void initialize()
// { out.println("HERE just entered initialize()") ; }
public DirectorySelectionWidgets()
{ super() ; }
@FXML
private void handleRootSelectionRequest(ActionEvent actionEvent)
{
Control control = (Control) actionEvent.getSource() ;
out.println(
"HERE control inside handleRootSelectionRequest control =>\n "
+ control
) ;
}
}
Das benutzerdefinierte Widget fxml Datei, DirectorySelectionWidgets.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.text.*?>
<GridPane id="rootSelectorPane" fx:id="rootSelectorPane" alignment="CENTER" gridLinesVisible="false" layoutY="42.0" maxWidth="1.7976931348623157E308" prefWidth="828.0" styleClass="root-selector-pane" xmlns:fx="http://javafx.com/fxml" >
<children>
<Button id="fromRootSelectionButton" fx:id="fromRootSelectionButton" alignment="CENTER" mnemonicParsing="false" onAction="#handleRootSelectionRequest" prefWidth="168.0" styleClass="root-selector-buttons" text="Set 'From' Root Directory" textAlignment="CENTER" GridPane.columnIndex="0" GridPane.halignment="CENTER" GridPane.hgrow="NEVER" GridPane.rowIndex="0" GridPane.valignment="CENTER" GridPane.vgrow="NEVER" />
</children>
<columnConstraints>
<ColumnConstraints fillWidth="false" halignment="LEFT" hgrow="NEVER" minWidth="-Infinity" prefWidth="166.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="-1.0" minHeight="-1.0" prefHeight="-1.0" vgrow="NEVER" />
</rowConstraints>
<stylesheets>
<URL value="@PuzzleCss.css" />
</stylesheets>
</GridPane>
Das benutzerdefinierte Widget Superklasse, Usercontrol .java:
package blogpost ;
/*
* Information link as of April 2016 is
* <A HREF="https://programmingwithpassion.wordpress.com/2013/07/07/creating-a-reusable-javafx-custom-control/">
* <I>Benjamin's programming Blog</I>.
* </A>
* <BR>
* Orginal copyright 2014 Benjamin Gale.
* License document is also there inside the Java file on his blog.
* <P>
* Modified in accordance with license.
*/
// Java imports
import java.io .IOException ;
import java.util.logging .Level ;
import java.util.logging .Logger ;
import java.net .URL ;
// JavaFX imports
import javafx.fxml .FXMLLoader ;
import javafx.geometry .HPos ;
import javafx.scene .Node ;
import javafx.scene.layout .Region ;
import javafx.geometry .VPos ;
/**
* This is a convenience class for creating custom controls that use the
* {@code FXMLLoader loader = new FXMLLoader() ;}
* approach. Mainly used for custom widgets.
* <P>
* Just subclass this class and all the FXMLLoader work is already done.
* <P>
* The only file restrictions are the following.
* <UL>
* <LI>
* The controller file and the fxml file must be in the same package.
* </LI>
* <LI>
* The fxml file must have the same (case sensitive) name (sans suffix)
* as the controller class.
* <BR>
* That is,
* if the controller file is named {@code MyController.java} then
* the fxml file must be named {@code MyController.fxml}.
* <BR>
* This also works with other JavaFX controller files; for example,
* {@code MyController.groovy} would work for Groovy developers.
* </LI>
* </UL>
*/
public abstract class UserControl extends Region
{
private final String resourcePath = "%s.fxml" ;
public UserControl()
{ this.loadView() ; }
/**
* A primary purpose for this class,
* make creating custom controls easier.
*/
private void loadView()
{
FXMLLoader fxmlLoader = new FXMLLoader() ;
fxmlLoader.setController(this) ;
fxmlLoader.setLocation(this.getViewURL()) ;
try
{
Node root = (Node) fxmlLoader.load() ;
setMaxSize(root) ;
this.getChildren().add(root) ;
}
catch (IOException ioException)
{
Logger.getLogger(UserControl.class.getName())
.log(Level.SEVERE, null, ioException) ;
}
}
private String getViewPath()
{ return String.format(resourcePath, this.getClass().getSimpleName()) ; }
private URL getViewURL()
{ return this.getClass().getResource(this.getViewPath()) ; }
@Override
protected void layoutChildren()
{
getChildren().stream().forEach(
(node) ->
{ layoutInArea(node, 0, 0,
getWidth(), getHeight(),
0,
HPos.LEFT, VPos.TOP
) ;
}
) ;
}
private void setMaxSize(Node node)
{
if (node != null && node instanceof Region)
{
Region region = (Region) node ;
region.setMaxWidth( Double.MAX_VALUE) ;
region.setMaxHeight(Double.MAX_VALUE) ;
}
}
}
Der Java-Testcode, DirectorySelectionWidgetsTest.java:
package blogpost ;
// JavaFX imports
import javafx.application .Application ;
import javafx.fxml .FXMLLoader ;
import javafx.scene .Parent ;
import javafx.scene .Scene ;
import javafx.stage .Stage ;
public class DirectorySelectionWidgetsTest extends Application
{
// Written this way while reducing code to smaller size and new locations.
protected String fxmlFullFileName = ""
+ "blogpost"
+ "/"
+ "DirectorySelectionWidgetsTest"
+ "."
+ "fxml" ;
protected String mainTitle = "Test directory selection widgets" ;
@Override
public void start(Stage stage)
throws Exception
{
FXMLLoader fxmlLoader = new FXMLLoader() ;
fxmlLoader.setController(this) ;
Parent root = fxmlLoader.load(
getClass().getClassLoader().getResource(fxmlFullFileName)
) ;
Scene scene = new Scene(root) ;
stage.setTitle(mainTitle) ;
stage.setScene(scene) ;
stage.show() ;
}
public static void main(String[] args)
{ launch(args) ; }
}
Das Test fxml Datei, DirectorySelectionWidgetsTest.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import blogpost.*?>
<AnchorPane id="anchorPane" fx:id="anchorPane" styleClass="header-title-pane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<DirectorySelectionWidgets id="selectionWidgets" fx:id="selectionWidgets" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
<stylesheets>
<URL value="@PuzzleCss.css" />
</stylesheets>
</AnchorPane>
Die CSS-Datei, PuzzleCss.css:
.root-selector-buttons
{
-fx-background-color :
green, linear-gradient(to bottom right, #FFFF00 40%, #99FF33 100%) ;
-fx-text-fill : black ;
}
.root-selector-pane
{
-fx-background-color : #DDFFBB ;
-fx-border-color : #DDFFBB ;
}
.rootSelectorTextFields
{
-fx-border-color : #00BB00 ;
-fx-text-fill : black ;
}
Ist es möglich, dass Sie [System.out auf null setzen] (http://stackoverflow.com/questions/18384033/what-are-the-scenarios-where-system-object-might-throw-a-null) -Zeiger-Ausnahme)? Andernfalls - bitte versuchen Sie, eine [MCVE] (http://stackoverflow.com/help/mcve) – Itai
Sillyfly, zum Glück, für mein Ego, das war nicht das Problem. Abgesehen von der CSS-Datei war der ursprüngliche Code der minimale, den ich verwenden konnte und trotzdem das Problem auftritt. Das Testprogramm wurde benötigt, um das benutzerdefinierte Widget in einer anderen FXML-Anwendung nachzuahmen, die Superklasse UserControl, die Interaktion mit der Unterklasse war das Hauptproblem. Ich habe versucht, es leicht zu machen, indem ich ein kurzes Segment auskommentierte. In Ihrem Kommentar wurde ich wirklich gefragt, warum die Unterklasseninstanzvariable null war, wenn das Setup nicht beendet wurde. Es ist ein Fehler aufgetreten, bevor Instanzvariablen in der Unterklasse festgelegt wurden. Antwort unten? – user2460422