I am at wit's end with SceneBuilder and Java FX's way of handling custom controls.
Do I use fx:root, or do I NOT use it? I opted to use it. So within the Controller+Root class of the control, I set itself as the root and controller, just as required. But it still says "Root hasn't been set. Use method setRoot() before load."
Within the parent FXML that will house the custom control, what am I supposed to import?
What is the correct classpath so that I can display my custom control in SceneBuilder 2.0? I don't quite understand the "/.../.../.../bin" thing at all.
With the new
<fx:include>
tag, is it necessary to use<MyCustomControl />
within the markup anymore?
So far, my custom control is nothing but a progress indicator, to avoid complications.
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.HBox?>
<fx:root type="HBox" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
<children>
<ProgressBar fx:id="progressBar" prefWidth="200.0" progress="0.0" />
</children>
</fx:root>
package application.ctrl;
import java.io.IOException;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.HBox;
import application.Main;
Its controller:
public class ProgressSelector extends HBox {
@FXML
private ProgressIndicator progressBar;
public ProgressSelector() {
FXMLLoader loader = new FXMLLoader(getClass().getResource(
Main.PROGRESS_SELECTOR));
loader.setRoot(this);
loader.setController(this);
loader.setClassLoader(this.getClass().getClassLoader());
try {
loader.load();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The parent FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.VBox?>
<?import application.ctrl.ProgressSelector?>
<VBox fx:id="vbox" spacing="5.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.ctrl.ObjectiveEditorCtrl">
<children>
<HBox>
<children>
<Button mnemonicParsing="false" onAction="#back" text="<" />
<Label text="Editing Objective:" />
</children>
</HBox>
<TextField fx:id="objectiveName" />
<ProgressSelector />
<HBox>
<children>
<Label text="Planned Start:" />
<Region HBox.hgrow="ALWAYS" />
<DatePicker fx:id="plannedStart" />
</children>
</HBox>
<HBox>
<children>
<Label text="Actual Start:" />
<Region HBox.hgrow="ALWAYS" />
<DatePicker fx:id="actualStart" />
</children>
</HBox>
<HBox>
<children>
<Label text="Planned Finish:" />
<Region HBox.hgrow="ALWAYS" />
<DatePicker fx:id="plannedFinish" />
</children>
</HBox>
<HBox>
<children>
<Label text="Actual Finish:" />
<Region HBox.hgrow="ALWAYS" />
<DatePicker fx:id="actualFinish" />
</children>
</HBox>
<HBox alignment="CENTER_RIGHT">
<children>
<Button mnemonicParsing="false" onAction="#save" text="Save" />
<Button mnemonicParsing="false" onAction="#back" text="Cancel" />
</children>
</HBox>
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</VBox>
Its controller:
package application.ctrl;
import interfaces.ControlledScreenInterface;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.DatePicker;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import application.ScreenController;
import application.objects.Objective;
public class ObjectiveEditorCtrl implements Initializable,
ControlledScreenInterface {
@FXML
private TextField objectiveName;
@FXML
private ProgressSelector completion;
@FXML
private DatePicker plannedStart;
@FXML
private DatePicker plannedFinish;
@FXML
private DatePicker actualStart;
@FXML
private DatePicker actualFinish;
@FXML
private VBox vbox;
private ScreenController parent;
private Objective current;
@Override
public void initialize(URL location, ResourceBundle resources) {
// TODO Auto-generated method stub
}
public void init(Objective current) {
this.current = current;
objectiveName.setText(current.getName());
// completion.setProgress(current.getCompletion());
plannedStart.setValue(current.getPlannedStart());
actualStart.setValue(current.getActualStart());
plannedFinish.setValue(current.getPlannedFinish());
actualFinish.setValue(current.getActualFinish());
}
public void save() {
// current.setName(objectiveName.getText());
// // current.setCompletion(completion.getProgress());
// current.setPlannedStart(plannedStart.getValue());
// current.setPlannedFinish(plannedFinish.getValue());
// current.setActualStart(actualStart.getValue());
// current.setActualFinish(actualFinish.getValue());
// back();
}
public void back() {
parent.back();
}
@Override
public void setParentScreen(ScreenController parent) {
this.parent = parent;
}
}