Prefill ListView in an application with FXML - javafx

I have JavaFX application using FXML to build its GUI.
When this application is launched, I need to have ListView, which has some values loaded, for example, from database. So, how can I do this?
I know how to make application, which loads items to ListView after user clicks a button, or something like this ("onAction" attribute in FXML). But this does not suites me as I need items to be loaded automaticaly to the ListView.

This fills my choicebox with the five predetermined baud rates. I assume if you try to add items from your controller, the list only shows those values (untested).
<ChoiceBox fx:id="baudRates" layoutX="234.0" layoutY="72.0">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="4800" />
<String fx:value="9600" />
<String fx:value="19200" />
<String fx:value="57600" />
<String fx:value="115200" />
</FXCollections>
</items>
</ChoiceBox>
You also need to include the following import statement in your FXML:
<?import javafx.collections.*?>

If you have fxml with Controller, like next:
<AnchorPane xmlns:fx="http://javafx.com/fxml" fx:controller="test.Sample">
<children>
<ListView fx:id="listView"/>
</children>
</AnchorPane>
you can just implement Initializable in your Controller:
public class Sample implements Initializable {
#FXML
private ListView listView;
#Override
public void initialize(URL url, ResourceBundle rb) {
// change next line to DB load
List<String> values = Arrays.asList("one", "two", "three");
listView.setItems(FXCollections.observableList(values));
}
}

Related

Controller For FXML based TableView Pagination

I have a customized TableView defined in an FXML and the table works fine so far. The code is something like the followings:
<FitWidthTableView fx:id="dataDisplayView" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="300.0" prefWidth="380.0" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="rowColumn" maxWidth="50.0" prefWidth="30.0" sortable="false" style="-fx-alignment: CENTER_RIGHT;" text="Row" />
...
</FitWidthTableView>
Now, I need to add the Pagination due to a huge amount of data (from a DB). It would be great if I can wrap around the TableView tag with the Pagination tag. I find a sample with the approach as the following
<Pagination fx:id="pagination" layoutX="2.0" layoutY="188.0" prefHeight="275.0" prefWidth="912.0">
<fx:define>
<FitWidthTableView fx:id="dataDisplayView" maxHeight="1.7976931348623157E308"
maxWidth="1.7976931348623157E308" prefHeight="300.0" prefWidth="380.0"
VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="rowColumn" maxWidth="50.0" prefWidth="30.0" sortable="false"
style="-fx-alignment: CENTER_RIGHT;" text="Row"/>
...
</columns>
<VBox.margin>
<Insets left="1.0" right="1.0"/>
</VBox.margin>
</FitWidthTableView>
</fx:define>
</Pagination>
while almost all examples of TableView with Pagination are done without FXML.
I, however, don't see the pagination controller code sample which shall do a few things: determine the number of pages, specify the page size, and populate data to the table. Can someone advise on the subject?
My controller is something like the followings:
public class DataViewerController implements Initializable {
#FXML
private Pagination pagination ;
#FXML
private FitWidthTableView<OutputData> dataDisplayView;
#FXML
private TableColumn<OutputData, Integer> rowColumn;
…
#Autowired
private OutputDataRepository outputDataRepository;
#Override // This method is called by the FXMLLoader when initialization is complete
#FXML
public void initialize(URL fxmlFileLocation, ResourceBundle resources) {
…
}
…
}
How to populate data with the above code structure?
As shown here, any Pagination property can be initialized in your FXML:
<Pagination pageCount="8" currentPageIndex="3" …/>
More likely, you'll derive the values based on your actual data. Your implementation of the pageFactory() should set the desired partition on the table and return a table view, as seen here.
I want to keep the TableView in the FXML.
As, #James_D comments, the TableView declaration is irrelevant to the pageFactory(). As a concrete example, start from the complete example cited here and substitute the following FXML declarations in center:
<center>
<Pagination fx:id="pager" currentPageIndex="1"/>
<fx:define>
<TableView fx:id="tableView" prefHeight="60.0">
<columns>
<TableColumn fx:id="itemName" text="Item Name" />
<TableColumn fx:id="pricePerUnit" text="Price Per Unit" />
<TableColumn fx:id="quantity" text="Quantity" />
<TableColumn fx:id="amount" text="Amount" />
</columns>
</TableView>
</fx:define>
</center>
In the controller, inject the pager and initialize() it:
#FXML
Pagination pager;
…
//tableView.setItems(objList);
pager.setPageCount(objList.size());
pager.setPageFactory((Integer pageIndex) -> createPage(pageIndex));
The following factory assigns a single row to the tableView and returns it:
public TableView<TestModel> createPage(int page) {
tableView.getItems().setAll(objList.get(page));
return tableView;
}

javaFX :: popup window launches, but controller doesn't...?

I am writing an app where I need the same custom popup window to appear when different buttons are clicked. Right now the popup is just a simple "Are You Sure? OK/Cancel" window, but later it will expand to include more customized features... so I can't use the quickie Dialog built-ins.
Here's the weird thing. When Button X is pushed, the popUp (defined in FXML) launches just fine, but my controller class doesn't seem to be running. I didn't think that you could do that. What I can't figure out is why the controller isn't running. I would have thought the app would crash if the controller wasn't working.
Here' the code a button will call to launch the popup:
private void popUpLaunch(Button caller){
Stage popUpStage = new Stage();
Parent root;
try {
root = FXMLLoader.load(getClass().getResource("popUp1.fxml"));
popUpStage.setScene(new Scene(root));
popUpStage.initModality(Modality.APPLICATION_MODAL); // popup
popUpStage.initOwner(caller.getScene().getWindow());
popUpStage.showAndWait();
} catch (IOException e) {
e.printStackTrace();
}
}
All of that works great. Here's the complete FXML, /src/sl/view/popUp1.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="130.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sl.view.PopUp1Controller">
<children>
<Text fx:id="popUpMessageText" layoutX="14.0" layoutY="14.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Message Goes Here" textAlignment="CENTER" wrappingWidth="577.6708984375" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<font>
<Font size="38.0" />
</font>
</Text>
<Button fx:id="btnPopUpOK" layoutX="126.0" layoutY="68.0" mnemonicParsing="false" prefHeight="31.0" prefWidth="157.0" text="OK" />
<Button fx:id="btnPopUpCancel" layoutX="286.0" layoutY="68.0" mnemonicParsing="false" prefHeight="31.0" prefWidth="169.0" text="Cancel" />
</children>
</AnchorPane>
The window loads just fine. And finally, here's the complete controller, /src/sl/view/PopUp1Controller.java:
package sl.view;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class PopUp1Controller {
#FXML Text popUpMessageText;
#FXML Button btnPopUpOK;
#FXML Button btnPopUpCancel;
Stage stage;
public void start(Stage stage) throws Exception{
System.out.println("Popup controller launched!"); // never reach this... so the controller is not launching???
this.stage = stage;
popUpMessageText.setText("Interesting message here!");
btnPopUpOK.setOnAction(event -> {
System.out.println("You cliced OK...");
});
btnPopUpCancel.setOnAction(event -> {
System.out.println("You cliced Cancel");
stage.close();
});
}
}
Some thoughts...
I used SceneBuilder to generate the FXML. When I assigned the Controller Class for that AnchorPane, I picked "sl.view.PopUp1Controller" from the drop-down menu. So I'm pretty sure that's right.
Also: I've looked through the other "JavaFX Popup" posts, but I don't see one that specifically addresses my issue. A lot of post are like the below post which are basically, "Why not use these other popup options rather than re-invent the wheel?" e.g.:
JavaFX 2 custom popup pane
In my case, I do want to reinvent the wheel, because I need my popups to carry more-then-usual functionality, they will not be simple dialog boxes.
If you want code in a controller to execute when the controller is initialized, put it in the initialize() method (see the documentation):
public class PopUp1Controller {
#FXML Text popUpMessageText;
#FXML Button btnPopUpOK;
#FXML Button btnPopUpCancel;
public void initialize() {
System.out.println("Popup controller launched!"); // never reach this... so the controller is not launching???
popUpMessageText.setText("Interesting message here!");
btnPopUpOK.setOnAction(event -> {
System.out.println("You cliced OK...");
});
btnPopUpCancel.setOnAction(event -> {
System.out.println("You cliced Cancel");
btnPopupCancel.getScene().getWindow().hide();
});
}
}

How do you get the SimpleMenuButton to display the MenuItem text in JavaFX?

I am building an inventory management system for work and am having a lot of trouble getting the SplitMenuButton to display the MenuItem when I click on the item. I can not find much information on the 'SplitMenuButton' on the internet and have tried just MenuButton as well with no luck. For example, the default text is 'Department' and I would like it to display 'Aseptic' when that menu item is selected or 'Facilities' when that menu item is selected.
I have tried to create a new instance of SplitMenuButton and setText("Aseptic") when the #buildDataAseptic method is run, but this still didn't work.
My fxml code is:
<SplitMenuButton mnemonicParsing="false" prefHeight="25.0" prefWidth="217.0" text="Department" textAlignment="CENTER">
<items>
<MenuItem fx:id="asepticMenuItem" mnemonicParsing="false" onAction="#buildDataAseptic" text="Aseptic" />
<MenuItem fx:id="generalMenuItem" mnemonicParsing="false" onAction="#buildDataGeneral" text="General" />
<MenuItem fx:id="facilitiesMenuItem" mnemonicParsing="false" onAction="#buildDataFacilities" text="Facilities" />
</items>
</SplitMenuButton>
any help is greatly appreacitead, thanks!
As others have pointed out, ComboBox is a much better choice for your use case.
Here is a self contained example. First the FXML:
<?import javafx.scene.control.ComboBox?>
<?import javafx.collections.FXCollections?>
<?import java.lang.String?>
<ComboBox xmlns:fx="http://javafx.com/javafx/null">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="Aseptic" />
<String fx:value="General" />
<String fx:value="Facilities" />
</FXCollections>
</items>
</ComboBox>
And the application with comments:
package sample;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.stage.Stage;
public class Main extends Application {
public void start(Stage primaryStage) throws Exception {
ComboBox<String> comboBox = FXMLLoader.load(getClass().getResource("test.fxml"));
// Create an observable property for the selection
SimpleStringProperty selected = new SimpleStringProperty();
// Bind the property to the comboBox
selected.bindBidirectional(comboBox.valueProperty());
// Set initial value
selected.set("Facilities");
// React to changes
selected.addListener((observable, oldValue, newValue) -> {
// newValue contains the new selection, update database
System.out.println(newValue);
});
primaryStage.setScene(new Scene(comboBox));
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
General advice: Don't hang on to the SplitMenuButton just because you've spent a lot of time on it. Think of this as a learning experience. If you don't learn to let go and refactor, you'll never create good software :)

Execute action when combobox item is selected FXML

I'm trying to create a drop down menu (using ComboBox) with FXML and JavaFX controllers.
This is what I already have:
<ComboBox fx:id="menuSettings" layoutX="14.0" layoutY="27.0" prefHeight="27.0" prefWidth="27.0" style="-fx-background-color: white;">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="Menu" />
<String fx:value="Settings" />
<String fx:value="Exit" />
</FXCollections>
</items>
</ComboBox>
How can I show a new scene using Action listeners when the ComboBox option is selected?
Thanks in advance!
There are two ways that come to mind on how you could do this.
The first would be to add the onAction="#yourMethod" to your <ComboBox ... > tag. You could then add some code to your controller...
#FXML public void yourMethod() {
//Show the scene here
}
...which would be run when the user selected an item.
The other thing that you could do would be to add a ChangeListener to your ComboBox:
#FXML public void initialize() {
yourComboBox.valueProperty().addListener(new ChangeListener<String>() {
#Override public void changed(ObservableValue value, String old, String new) {
//Show your scene here
}
});
}
Both of these work I think, it's just a matter of preference to do it in code or FXML.
I hope this was helpful, and good luck with your project!
(If this did not answer your question, please let me know and I will do my best to revise my answer)

how to display a calendar controller from a fxml file in javafx

Is that possible to display a calendar controller from scene builder? I am trying to display a calendar which ideally has to be linked to a data property and time slot. Any help?
I'm not using scene builder, but you can manually edit your fxml to add a DatePicker. I created a simple example that shows a date picker and when the date is chosen it displays it in a Text field below.
The fxml looks like:
<GridPane fx:controller="datepicker.DatePickerController" xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
<padding>
<Insets top="25" right="25" bottom="10" left="25" />
</padding>
<DatePicker fx:id="datepicker" GridPane.columnIndex="0" GridPane.rowIndex="0" onAction="#handleDatePickerAction"></DatePicker>
<Text fx:id="actiontarget" GridPane.columnIndex="0" GridPane.rowIndex="1" />
</GridPane>
And the controller looks like:
public class DatePickerController
{
#FXML
private Text actiontarget;
#FXML
private DatePicker datepicker;
#FXML
protected void handleDatePickerAction(ActionEvent event)
{
actiontarget.setText(datepicker.getValue().toString());
}
}

Resources