Issue
I am query Sql Server and returning a List - I want to use this List as the source for my combobox. Below is the code that I am using, and it runs error free, but my combobox is always empty and never populated. What is incorrect here?
public class Controller {
private List<String> combomain;
static String getData = "QueryHEre";
void initialize() {
empnames = queryDatabase(getData);
String[] names = empnames.toArray(new String[0]);
combomain.getItems().addAll(names);
combomain.setValue("");
}
Main.java
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 350, 275));
primaryStage.show();
}
sample.fxml
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="399.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<FlowPane hgap="10.0" layoutX="14.0" layoutY="7.0" prefHeight="30.0" prefWidth="375.0">
<children>
<Label alignment="CENTER_RIGHT" prefHeight="17.0" prefWidth="79.0" text="Employee:" />
<ComboBox id="combomain" fx:id="combomain" prefWidth="150.0" />
<Button mnemonicParsing="false" prefHeight="27.0" prefWidth="80.0" text="Get Info" />
</children>
</FlowPane>
</children>
</Pane>
Solution
Are you sure that code runs without errors? You have combomain
defined as a List<String>
, which should mean combomain.getItems()
and combomain.setValue("")
will result in compilation errors. Based on your FXML file, that field should instead be a ComboBox<String>
. However, even if you fix that, your initialize
method is not being invoked, and neither is your combomain
being injected. From Introduction to FXML:
Note that, in the previous examples, the controller member fields and event handler methods were declared as public so they can be set or invoked by the loader. In practice, this is not often an issue, since a controller is generally only visible to the FXML loader that creates it. However, for developers who prefer more restricted visibility for controller fields or handler methods, the
javafx.fxml.FXML
annotation can be used. This annotation marks a protected or private class member as accessible to FXML. If the class being annotated is in a named module, the module containing that class mustopen
the containing package to at least thejavafx.fxml
module.
Since your initialize
method is not public
, it must be annotated with @FXML
in order for it to be seen and invoked by the FXMLLoader
. Same thing with your combomain
field; despite having the appropriate fx:id
in the FXML file, it won't be injected because the field is private
and is not annoated with @FXML
.
Your controller should look like this:
public class Controller {
@FXML
private ComboBox<String> combomain;
static String getData = "QueryHEre";
@FXML
void initialize() {
empnames = queryDatabase(getData);
String[] names = empnames.toArray(new String[0]);
combomain.getItems().addAll(names);
combomain.setValue("");
}
}
However, even with all that fixed this still won't work because you haven't linked your controller class to the FXML file. As mentioned in the previous section of Introduction to FXML, one way of doing this is by specifying an fx:controller
attribute in the root element of the FXML file:
<!-- SOME ATTRIBUTES OMITTED FOR BREVITY -->
<Pane xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="sample.Controller">
<!-- OMITTED FOR BREVITY -->
</Pane>
Where sample.Controller
should be replaced with the fully qualified name of your controller class. If you're using Scene Builder, you can set the controller by opening the "Controller" titled pane in the "Document" section (left panel).
Answered By - Slaw