0

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>
Slaw
  • 37,820
  • 8
  • 53
  • 80
Doctor Ford
  • 440
  • 1
  • 5
  • 17

1 Answers1

2

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 must open the containing package to at least the javafx.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).

Slaw
  • 37,820
  • 8
  • 53
  • 80
  • I changed my controller to be like this, but combobox is still empty ``` @FXML public ComboBox combomain; @FXML public void initialize() { } ``` – Doctor Ford Apr 18 '19 at 13:31
  • I think my initialize method is never being called bc if I add in System.out.printf(rs.getString(1)); to the queryDatabase method nothing is printed. – Doctor Ford Apr 18 '19 at 13:36
  • @DoctorFord Edited answer. You also need to link your controller to the FXML file. – Slaw Apr 18 '19 at 13:41
  • Does order of 'elements' matter for my Pane? For example, could I add the fx:controller first? And I am now getting a db connect error so yes this has resolved my issue. Thank you! – Doctor Ford Apr 18 '19 at 13:43
  • @DoctorFord An FXML file is fundamentally an XML file, where [attribute order is not significant](https://stackoverflow.com/questions/33746224/in-xml-is-the-attribute-order-important). – Slaw Apr 18 '19 at 13:46