Search code examples
javamysqljavafxjavafx-8fxml

JavaFX How to add elements eg. Buttons dynamically created from items stored in the database Mysql?


There is this video in youtube https://www.youtube.com/watch?v=Idtm2Y6I23w Whereby the person has dynamically populated buttons created from the items that are stored in the database.For instance in this picture enter image description here

It has some categories that includes Tables,Stock,Reports and Users When a user clicks on the Table category it displays Buttons dynamically created from items stored in the database mysql. For instance this is the result image: enter image description here

How does one get to develop like that? Is there a for loop statements that is going to be used?

EDIT

This is how i did it.This is the source code.

public class OrderController implements Initializable {

    @FXML
    private ListView<Button> listvieww;

    @FXML
    private HBox hboxx;

    List<String> listOfSomething = null;
//@FXML
//    private Pane panedynamic;
    private DBConnection database = new DBConnection();
    private Connection connection;
    private Statement statement;
    private ResultSet resultSet;

    private ObservableList<Button> buttons = FXCollections.observableArrayList();

    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
    hboxx.getChildren().add(buttons)
    }

    @FXML
    void acttable(ActionEvent event) {

        // TODO
        String sqlQuery = "SELECT * FROM restauranttables;";
        try {
            connection = database.getConnection();
            statement = connection.createStatement();
            resultSet = statement.executeQuery(sqlQuery);
            while (resultSet.next()) {
                String current = resultSet.getString("tablename");
                ObservableList<String> list = FXCollections.observableArrayList(current);
                Button b = new Button(list.toString());
                buttons.add(b);

            }

        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

    @FXML
    void actlogout(ActionEvent event) {

    }

    @FXML
    void actnew(ActionEvent event) {

    }

    @FXML
    void actorder(ActionEvent event) {

    }

    @FXML
    void actreports(ActionEvent event) {

    }

    @FXML
    void actstock(ActionEvent event) {

    }



    @FXML
    void actusers(ActionEvent event) {

    }

}

this is how my scene builder looks like

<?xml version="1.0" encoding="UTF-8"?>

<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXTextField?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.StackPane?>

<AnchorPane id="AnchorPane" prefHeight="600.0" prefWidth="1080.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.OrderController">
    <children>
        <AnchorPane layoutX="55.0" layoutY="29.0" prefHeight="600.0" prefWidth="1080.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
            <children>
                <TableView layoutX="21.0" layoutY="49.0" prefHeight="386.0" prefWidth="413.0">
                    <columns>
                        <TableColumn prefWidth="122.0" text="Description" />
                        <TableColumn prefWidth="57.0" text="Price" />
                        <TableColumn prefWidth="81.0" text="Sub Total" />
                        <TableColumn prefWidth="96.0" text="Table Id" />
                        <TableColumn prefWidth="57.0" text="Price" />
                    </columns>
                </TableView>
                <JFXTextField layoutX="53.0" layoutY="439.0" prefHeight="37.0" prefWidth="155.0" />
                <JFXTextField layoutX="253.0" layoutY="439.0" prefHeight="37.0" prefWidth="155.0" />
                <GridPane layoutX="63.0" layoutY="503.0" prefHeight="75.0" prefWidth="345.0">
                    <columnConstraints>
                        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                    </columnConstraints>
                    <rowConstraints>
                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                    </rowConstraints>
                    <children>
                        <AnchorPane prefHeight="200.0" prefWidth="200.0">
                            <children>
                                <JFXButton layoutX="25.0" layoutY="25.0" onAction="#actorder" prefHeight="75.0" prefWidth="173.0" text="Order" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
                            </children>
                        </AnchorPane>
                        <AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
                            <children>
                                <JFXButton layoutX="39.0" layoutY="14.0" onAction="#actnew" prefHeight="75.0" prefWidth="172.0" text="New" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
                            </children>
                        </AnchorPane>
                    </children>
                </GridPane>
                <MenuBar layoutX="21.0" layoutY="14.0" prefHeight="29.0" prefWidth="413.0">
                    <menus>
                        <Menu mnemonicParsing="false" text="File">
                            <items>
                                <MenuItem mnemonicParsing="false" text="Close" />
                            </items>
                        </Menu>
                        <Menu mnemonicParsing="false" text="Edit">
                            <items>
                                <MenuItem mnemonicParsing="false" text="Delete" />
                            </items>
                        </Menu>
                        <Menu mnemonicParsing="false" text="Help">
                            <items>
                                <MenuItem mnemonicParsing="false" text="About" />
                            </items>
                        </Menu>
                    </menus>
                </MenuBar>
                <StackPane fx:id="acContent" layoutX="454.0" layoutY="49.0" prefHeight="525.0" prefWidth="605.0">
                    <children>
                        <AnchorPane fx:id="anchora" prefHeight="200.0" prefWidth="200.0">
                           <children>

                               <GridPane fx:id="sasa" layoutX="17.0" layoutY="7.0" prefHeight="90.0" prefWidth="571.0">
                                   <columnConstraints>
                                       <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                                       <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                                       <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                                       <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                                       <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                                   </columnConstraints>
                                   <rowConstraints>
                                       <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                                   </rowConstraints>
                                   <children>
                                       <AnchorPane prefHeight="200.0" prefWidth="200.0">
                                           <children>
                                               <JFXButton fx:id="table" layoutX="37.0" layoutY="19.0" onAction="#acttable" prefHeight="90.0" prefWidth="135.0" text="TABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
                                           </children>
                                       </AnchorPane>
                                       <AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
                                           <children>
                                               <JFXButton fx:id="stock" layoutX="43.0" layoutY="32.0" onAction="#actstock" prefHeight="90.0" prefWidth="134.0" text="STOCK" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
                                           </children>
                                       </AnchorPane>
                                       <AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
                                           <children>
                                               <JFXButton fx:id="reports" layoutX="26.0" layoutY="32.0" onAction="#actreports" prefHeight="90.0" prefWidth="134.0" text="REPORTS" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
                                           </children>
                                       </AnchorPane>
                                       <AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3">
                                           <children>
                                               <JFXButton fx:id="users" layoutX="26.0" layoutY="32.0" onAction="#actusers" prefHeight="90.0" prefWidth="134.0" text="USERS" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
                                           </children>
                                       </AnchorPane>
                                       <AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="4">
                                           <children>
                                               <JFXButton fx:id="logout" layoutX="28.0" layoutY="32.0" onAction="#actlogout" prefHeight="90.0" prefWidth="134.0" text="LOGOUT" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
                                           </children>
                                       </AnchorPane>
                                   </children>
                               </GridPane>
                        <HBox fx:id="hboxx" layoutX="17.0" layoutY="110.0" prefHeight="398.0" prefWidth="571.0" />
                           </children>
                        </AnchorPane>
                    </children>
                </StackPane>
            </children>
        </AnchorPane>
    </children>
</AnchorPane>

i would want to align the buttons in a hbox but am getting an error here

@Override
    public void initialize(URL url, ResourceBundle rb) {
    hboxx.getChildren().add(buttons)
    }

Any Help Thank you.


Solution

  • The workflow you would like to implement:

    1. Retrieve some information from DB based on an action event
    2. For every row returned from (1)-> create a Button
    3. Add all created Buttons to some container

      @FXML
      void acttable(ActionEvent event) {
      
      String sqlQuery = "SELECT * FROM restauranttables;";
      List<Button> buttonlist = new ArrayList<>(); //our Collection to hold newly created Buttons
      try {
          connection = database.getConnection();
          statement = connection.createStatement();
          resultSet = statement.executeQuery(sqlQuery);
          while (resultSet.next()) { //iterate over every row returned
              String restaurant = resultSet.getString("restaurantname"); //extract button text, adapt the String to the columnname that you are interested in
              buttonlist.add(new Button(restaurant));
      
          }
          hboxx.getChildren().clear(); //remove all Buttons that are currently in the container
          hboxx.getChildren().addAll(buttonlist); //then add all your Buttons that you just created
      
      } catch (SQLException e) {
          e.printStackTrace();
      } finally{
          resultSet.close();
          statement.close();
          connection.close;
      }
      }
      

    So as workflow, what happens up there:

    1. you create a List that will hold all your new Buttons.
    2. you execute a query
    3. you iterate over the ResultSet from 2
    4. you grab the String value that you want to set as Button Text
    5. you add that Button to the List
    6. you clear your HBox from previously added Buttons
    7. you add all the new Buttons to your HBox

    edit: don't forget to close the ResultSet, Statement and Connection. If you would switch your try/catch to a try with resources you can avoid the explicit .close() since all three objects implement the Autoclosable interface. I added a "finally" statement that will be executed when your try block exits. You also might check for resultSet/statement/connection being null.