I'm trying to create a material inventory program that uses a tableview. I have a controller that will show statistics based on that tableview but I'm not sure how to access the live data from that view.
My MainApp loads the last saved table and my MaterialOverviewController has the tableview.
I have a RootLayoutController which is my main layout controller which has a simple file menu but also is where the OnFloorStatsController is loaded from.
I can obviously create a new MainApp when the OnFloorStatsController is loaded but this only loads the sample data that was entered by default.
How do I access the live data from the MainApp?
Here is my MainApp code:
public class MainApp extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
private ObservableList<Material> materialData = FXCollections.observableArrayList();
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Label Inventory");
this.primaryStage.getIcons().add(new Image("file:resources/images/1462487405_Mask.png"));
initRootLayout();
showMaterialOverview();
}
public MainApp() {
// Add some sample data
}
public ObservableList<Material> getMaterialData() {
return materialData;
}
/**
* Initializes the root layout and tries to load the last opened
* material file.
*/
public void initRootLayout() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class
.getResource("RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
// Give the controller access to the main app.
RootLayoutController controller = loader.getController();
controller.setMainApp(this);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
// Try to load last opened person file.
File file = getMaterialFilePath();
if (file != null) {
loadMaterialDataFromFile(file);
}
}
public void showMaterialOverview() {
try {
// Load material overview.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("MaterialOverview.fxml"));
AnchorPane materialOverview = (AnchorPane) loader.load();
// Set material overview into the center of root layout.
rootLayout.setCenter(materialOverview);
// Give the controller access to the main app.
MaterialOverviewController controller = loader.getController();
controller.setMainApp(this);
} catch (IOException e) {
e.printStackTrace();
}
}
public void showOnFloorStatistics() {
try {
// Load the fxml file and create a new stage for the popup.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("OnFloorStats.fxml"));
AnchorPane page = (AnchorPane) loader.load();
Stage dialogStage = new Stage();
dialogStage.setTitle("Material On Floor");
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(primaryStage);
Scene scene = new Scene(page);
dialogStage.setScene(scene);
// Set the material into the controller.
OnFloorStatsController controller = loader.getController();
controller.start(dialogStage);
dialogStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public void showBarChartTest() {
try {
// Load the fxml file and create a new stage for the popup.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("BarChartTestLayout.fxml"));
AnchorPane page = (AnchorPane) loader.load();
Stage dialogStage = new Stage();
dialogStage.setTitle("Detailed Bar Chart");
//
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(primaryStage);
Scene scene = new Scene(page);
dialogStage.setScene(scene);
// Set the material into the controller.
BarChartTest controller = loader.getController();
controller.start(dialogStage);
dialogStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Returns the main stage.
* #return
*/
public Stage getPrimaryStage() {
return primaryStage;
}
public static void main(String[] args) {
launch(args);
}
}
And here is my MaterialOverViewController code:
public class MaterialOverviewController {
#FXML
private TableView<Material> materialTable;
private List<Material> materialId;
public TableView<Material> getMaterialTable() {
return materialTable;
}
// public void setMaterialTable(TableView<Material> materialTable) {
// this.materialTable = materialTable;
}
private ObservableList<Integer> rollsTotal = FXCollections.observableArrayList();
private ObservableList<String> materialNames = FXCollections.observableArrayList();
// Reference to the main application.
private MainApp mainApp;
/**
* The constructor.
* The constructor is called before the initialize() method.
*/
public MaterialOverviewController() {
}
/**
* Initializes the controller class. This method is automatically called
* after the fxml file has been loaded.
*/
#FXML
private void initialize() {
materialTotal = 0;
// Initialize the material table with columns.
pONumberColumn.setCellValueFactory(cellData -> cellData.getValue().pONumberProperty());
materialNameColumn.setCellValueFactory(cellData -> cellData.getValue().materialNameProperty());
materialIdColumn.setCellValueFactory(cellData -> cellData.getValue().materialIdProperty());
materialWidthColumn.setCellValueFactory(cellData -> cellData.getValue().materialWidthProperty().asObject());
qtyOrderedColumn.setCellValueFactory(cellData -> cellData.getValue().qtyOrderedProperty().asObject());
qtyReceivedColumn.setCellValueFactory(cellData -> cellData.getValue().qtyReceivedProperty().asObject());
qtyBackOrderedColumn.setCellValueFactory(cellData -> cellData.getValue().qtyBackOrderedProperty().asObject());
// qtyBackOrderedColumn.setCellValueFactory(cellData -> cellData.getValue().qtyBackOrderedProperty().asObject());
qtyOnFloorColumn.setCellValueFactory(cellData -> cellData.getValue().qtyOnFloorProperty().asObject());
// dateOrderedColumn.setCellValueFactory(cellData -> cellData.getValue().dateOrderedProperty().asString());
dateOrderedColumn.setCellValueFactory(cellData -> cellData.getValue().dateOrderedProperty().asString());
estArrivalColumn.setCellValueFactory(cellData -> cellData.getValue().dateExpectedProperty().asString());
supplierColumn.setCellValueFactory(cellData -> cellData.getValue().supplierProperty());
// Clear material details.
showMaterialDetails(null);
// Listen for selection changes and show the material details when changed.
materialTable.getSelectionModel().selectedItemProperty().addListener(
(observable, oldValue, newValue) -> showMaterialDetails(newValue));
}
public void setMainApp(MainApp mainApp) {
this.mainApp = mainApp;
// Add observable list data to the table
materialTable.setItems(mainApp.getMaterialData());
}
private void showMaterialDetails(Material material) {
if (material != null) {
// Fill the labels with info from the material object.
pONumberLabel.setText(material.getPoNumber());
materialIdLabel.setText(material.getMaterialId());
materialNameLabel.setText(material.getMaterialName());
materialWidthLabel.setText(String.valueOf(material.getMaterialWidth()));
qtyOrderedLabel.setText(Integer.toString(material.getQtyOrdered()));
qtyRecievedLabel.setText(Integer.toString(material.getQtyReceived()));
qtyBackOrderedLabel.setText(Integer.toString(material.getQtyOrdered()-material.getQtyReceived()));
// qtyBackOrderedLabel.setText(Integer.toString(material.getQtyBackOrdered()));
qtyOnFloorLabel.setText(Integer.toString(material.getQtyOnFloor()));
// dateOrderedLabel.setText(DateUtil.format(material.getDateOrdered()));
// dateOrderedLabel.equals(DateUtil.format(material.getDateOrdered()));
// dateOrderedLabel.setText(DatePicker(String.valueOf(material.getDateOrdered());
// estArrivalLabel.setText(material.getSupplier());
supplierLabel.setText(material.getSupplier());
String pattern = "MM/dd/yyyy";
// dateTestTextField.setText(DateUtil.format(material.getBirthday()));
dateOrderedLabel.setText(DateUtil.format(material.getDateOrdered()));
estArrivalLabel.setText(DateUtil.format(material.getDateExpected()));
//TODO: set running material totals
// getMaterialNames(Arrays.asList(material));
handleSelectMaterial();
}
}
}
public List getMaterialNames(List<Material> materials) {
for (Material name : materials) {
mainApp.getMaterialData();
if (!materialNames.contains(name)) {
materialNames.add(name.getMaterialName());
}
}
for (String name : materialNames) {
materialTextField.setText(name + "\n");
}
return Arrays.asList(materialNames);
}
}
}
Here is the bit of code that works from my RootLayoutController but I'm not sure why I can't do the same thing from the OnFloorStatsController:
public void setMainApp(MainApp mainApp) {
this.mainApp = mainApp;
}
#FXML
private void handlePrint() {
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("MaterialOverview.fxml"));
try {
AnchorPane frame = fxmlLoader.load();
} catch (IOException e) {
e.printStackTrace();
}
MaterialOverviewController c = fxmlLoader.getController();
//Loads data into table
c.setMainApp(mainApp);
I just need access to the live data from the MaterialOvewViewController
Here's the OnFloorStatsController:
private MainApp mainApp;
public TableView<Material> material;
/**
* Is called by the main application to give a reference back to itself.
*
* #param mainApp
*/
public void setMainApp(MainApp mainApp) {
this.mainApp = mainApp;
}
// final static String austria = "14532";
// final static String brazil = "78333";
// final static String france = "40443";
// final static String italy = "72825";
// final static String usa = "72829";
public void start(Stage stage) {
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("MaterialOverview.fxml"));
try {
AnchorPane frame = fxmlLoader.load();
} catch (IOException e) {
e.printStackTrace();
}
MaterialOverviewController c = fxmlLoader.getController();
//Loads data into table
c.setMainApp(mainApp);
stage.setTitle("Material On Floor");
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
final BarChart<String, Number> bc =
new BarChart<String, Number>(xAxis, yAxis);
bc.setTitle("Material On Floor");
xAxis.setLabel("Material");
yAxis.setLabel("Quantity");
XYChart.Series series1 = new XYChart.Series();
series1.setName("6 inch");
Integer floorTotal = 0;
for (Material id :mainApp.getMaterialData()) {
if (id.getMaterialWidth() < 6.9) {
floorTotal = id.getQtyOnFloor();
for (Material size : mainApp.getMaterialData()) {
if ( id.getMaterialId().equalsIgnoreCase(size.getMaterialId()) &&
size.getMaterialWidth() == id.getMaterialWidth()) {
floorTotal += size.getQtyOnFloor();
}
else {
floorTotal = id.getQtyOnFloor();
}
Related
So I'm trying to load and save Images into an imageView where the location of the image is chosen through a file browser. I've been working on this for several days now and I'm gonna have a stroke if I can't get it fixed. I've tried everything I can think of. Thank you in advance for helping.
UPDATED:
Here is my main class:
public class Main extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
public Main(){}
#Override
public void start(Stage primaryStage) throws Exception{
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Help Please");
initRootLayout();
showScreen();
}
public void initRootLayout(){
try{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
RootLayout controller = loader.getController();
controller.setMain(this);
primaryStage.show();
}catch(Exception e ){e.printStackTrace();}
}
public void showScreen(){
try{FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/sample.fxml"));
BorderPane sample = (BorderPane)loader.load();
rootLayout.setCenter(sample);
Controller controller = loader.getController();
controller.setMain(this);
}catch (Exception e){e.printStackTrace();}
}
public Stage getPrimaryStage(){return primaryStage;}
public static void main(String[] args) {
launch(args);
}
}
Here is the rootLayout:
public class RootLayout {
private Main main;
private Controller controller = new Controller();
public void setMain(Main main){this.main = main;}
#FXML
private void handleOpen(){
FileChooser fileChooser = new FileChooser();
FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter(
"PNG files (*.png)","*png");
fileChooser.getExtensionFilters().add(extensionFilter);
File file = fileChooser.showOpenDialog(main.getPrimaryStage());
if(file!= null){
controller.updateImage(file.toURI().toString());
}
}
}
And here is the controller:
public class Controller implements Initializable {
#FXML
ImageView imageView = new ImageView();
String imageURL;
Main main = new Main();
public void setMain(Main main){
this.main = main;
}
public void updateImage(String url){
if(url.length()>=1){
Image image = new Image(url);
imageView.setImage(image);
System.out.println(url);
}
else{
System.out.println(url);
System.out.println("image invalid");
}
}
#Override
public void initialize(URL location, ResourceBundle resources) {
}
}
Two things:
Never assign a field whose value is to be injected by an FXMLLoader (e.g. #FXML fields). Doing so is a waste of resources at best and introduces subtle bugs at worst. For instance, if you were to leave the imageView field uninitialized you'd be getting a NullPointerException which would indicate a problem with your setup. Since you do initialize the field, however, you don't get any errors and there's a false impression of the code working.
In your RootLayout controller class, you have:
private Controller controller = new Controller();
That instance of Controller you just created is not linked to any FXML file. And since you initialize the imageView field (see first point) you end up updating an ImageView which is not being displayed anywhere; this is where not initializing said field would have given a nice indication of there being a problem. The solution is to pass the Controller instance created by the FXMLLoader to the RootLayout instance created by the other FXMLLoader.
Also, in the same class you have:
Main main = new Main();
Which is also unnecessary since the created instance of Main is both not the correct instance and is replaced by the call to #setMain(Main) almost immediately.
Assuming your FXML files (which you did not provide) are correct, the Java classes should look more like:
Main.java
public class Main extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
private RootLayout rootLayoutController;
public Main() {}
#Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Help Please");
initRootLayout();
showScreen();
}
public void initRootLayout() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
// store RootLayout instance in field so #showScreen()
// can reference it
rootLayoutController = loader.getController();
rootLayoutController.setMain(this);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public void showScreen() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/sample.fxml"));
BorderPane sample = (BorderPane) loader.load();
rootLayout.setCenter(sample);
Controller controller = loader.getController();
controller.setMain(this);
// set Controller instance on RootLayout instance
rootLayoutController.setController(controller);
} catch (Exception e) {
e.printStackTrace();
}
}
public Stage getPrimaryStage() {
return primaryStage;
}
public static void main(String[] args) {
launch(args);
}
}
RootLayout.java
public class RootLayout {
private Main main;
private Controller controller;
public void setMain(Main main) {
this.main = main;
}
public void setController(Controller controller) {
this.controller = controller;
}
#FXML
private void handleOpen() {
FileChooser fileChooser = new FileChooser();
// Note extensions should be prefixed with "*."
FileChooser.ExtensionFilter extensionFilter =
new FileChooser.ExtensionFilter("PNG files (*.png)", "*.png");
fileChooser.getExtensionFilters().add(extensionFilter);
File file = fileChooser.showOpenDialog(main.getPrimaryStage());
if (file != null) {
controller.updateImage(file.toURI().toString());
}
}
}
Controller.java
public class Controller implements Initializable {
#FXML ImageView imageView; // leave uninitialized, will be injected
String imageURL;
Main main;
public void setMain(Main main) {
this.main = main;
}
public void updateImage(String url) {
if (url.length() >= 1) {
Image image = new Image(url);
imageView.setImage(image);
System.out.println(url);
} else {
System.out.println(url);
System.out.println("image invalid");
}
}
#Override
public void initialize(URL location, ResourceBundle resources) {}
}
Note: Did not test new code.
I am playing around with SceneBuilder and come across a few questions about the intialize() method and how to change ComboBox items after it's already been initialized in said method. So basically, after I set the items in initialize, I am not able to change them anymore from another method in the controller.
Here is my code:
public class AppController implements Initializable {
private ObservableList<String> list = FXCollections.observableArrayList();
private MainModel model;
#FXML
private ComboBox<String> cobUsers = new ComboBox<String>();
#Override
public void initialize(URL url, ResourceBundle rb) {
list.add("name1");
list.add("name2");
cobUsers.setItems(list); // this works!
}
public void initModel(MainModel model) {
this.model = model;
}
public void addItems(){
list.add("name3");
list.add("name4");
cobUsers.setItems(list); // this does not work. ComboBox items remain "name1" and "name2"
}
}
public class App extends Application {
private Stage primaryStage;
private AnchorPane rootLayout;
private AppController appController = new AppController();
MainModel model = new MainModel();
#Override
public void start(Stage primaryStage) {
appController.initModel(model);
this.primaryStage = primaryStage;
this.primaryStage.setTitle("App");
initRootLayout();
appController.addItems();
}
/**
* Initializes the root layout.
*/
public void initRootLayout() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("FXMLDocument.fxml"));
rootLayout = (AnchorPane) loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
So guess my question is, how can I access/change my ComboBox later on, after it's been initialized in intialize()?
Thanks! :)
UPDATE 1:
I have changed the initRootLayout() in the App class (see below) and it WORKS now. list now contains 4 items and all of them show up in the ComboBox after calling addItems(). Thanks everyone!
public void initRootLayout() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("FXMLDocument.fxml"));
rootLayout = (AnchorPane) loader.load();
AppController controller = loader.<AppController>getController();
controller.addItems();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
Let's say I've got 3 views and 3 controllers:
LogInController, LogInView
MainMenuController, MainMenuView
ListOfPatientsInternalMedicineController, ListOfPatientsInternalMedicineView.
An internalMedicineButtonClicked method change my scene to another (with some other content) but in this new scene, I want to have a button which allows me to go back to MainMenu (goBacktoMainMenuButtonClicked() method). And here occures my problem. How am I able to get reference to MainMenuController (the one which is corresponding with fxml file, created in LogInController) to fill setController() method.
public class LogInController {
MainMenuController mainMenuController = new MainMenuController();
#FXML
private JFXTextField logInTextField;
#FXML
private JFXButton logInButton;
#FXML
private JFXPasswordField passwordTextField;
#FXML
void logInButtonClicked(ActionEvent event) throws IOException {
LogInDAO logInDAO = new LogInDAO();
if(logInDAO.checkIfLoginAndPasswordIsCorrect(logInTextField.getText(),passwordTextField.getText()))
{
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/MainMenu.fxml"));
Window window = logInButton.getScene().getWindow();
Stage stage = (Stage) window;
loader.setController(mainMenuController); // here i'm passing original controller corresponding with fmxl
stage.setScene(new Scene(loader.load()));
}
else
{
(...)
}
}
}
MainMenuCotroller class:
public class MainMenuController {
ContentOfPatientTableView patientTableViewModel = new ContentOfPatientTableView();
(..)
#FXML
void internalMedicineButtonClicked(ActionEvent event) throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/ListOfPatientsInternalMedicineView.fxml"));
Button button = (Button) event.getSource();
Scene scene = button.getScene();
Stage stage = (Stage) scene.getWindow();
loader.setController(new ListOfPatientsInternalMedicineController(patientTableViewModel));
stage.setScene(new Scene(loader.load()));
}
And ListOfPatientsInternalMedicineController class;
public class ListOfPatientsInternalMedicineController {
IPatientDAO patientDAO = new PatientDAO();
ContentOfPatientTableView patientTableViewModel;
public ListOfPatientsInternalMedicineController(ContentOfPatientTableView content) {
patientTableViewModel=content;
}
#FXML
public void goBacktoMainMenuButtonClicked(ActionEvent event)
{
FXMLLoader loader = new FXMLLoader(MainMenuController.class.getResource("/fxml/MainMenuView.fxml");
loader.setController(?????????); // Here if I will pass new MainController() i will create new instance, not this which is corresponding with fxml file. How am I able to refer to instance MainController created in LogInController ?
}
}
Consider using another model to represent the current view. You could implement this along the following lines:
public class ViewState {
private final ContentOfPatientTableView patientTableViewModel ;
private final ReadOnlyObjectWrapper<Parent> currentView = new ReadOnlyObjectWrapper<>();
private Parent logInView ;
private Parent mainMenuView ;
private Parent listOfPatientsMainMedicineView ;
public ViewState(ContentOfPatientTableView patientTableViewModel) {
this.patientTableViewModel = patientTableViewModel ;
}
public ReadOnlyObjectProperty<Parent> currentViewProperty() {
return currentView.getReadOnlyProperty();
}
public void showLogIn() {
if (logInView == null) {
try {
FXMLLoader loader = new FXMLLoader("/fxml/LogIn.fxml");
loader.setController(new LogInController(this));
logInView = loader.load();
} catch (IOException exc) {
// fatal...
throw new UncheckedIOException(exc);
}
}
currentView.set(logInView);
}
public void showMainMenu() {
// similarly...
}
public void showListOfPatientsMainMedicineView() {
// ...
}
}
Now your LogInController can do:
public class LogInController {
private final ViewState viewState ;
#FXML
private JFXTextField logInTextField;
#FXML
private JFXButton logInButton;
#FXML
private JFXPasswordField passwordTextField;
public LogInController(ViewState viewState) {
this.viewState = viewState ;
}
#FXML
void logInButtonClicked(ActionEvent event) {
LogInDAO logInDAO = new LogInDAO();
if(logInDAO.checkIfLoginAndPasswordIsCorrect(logInTextField.getText(),passwordTextField.getText()))
{
viewState.showMainMenu();
}
else
{
(...)
}
}
}
Similarly,
public class MainMenuController {
private final ViewState viewState ;
public MainMenuController(ViewState viewState) {
this.viewState = viewState ;
}
#FXML
void internalMedicineButtonClicked(ActionEvent event) throws IOException {
viewState.showListOfPatientsMainMedicineView();
}
}
and similarly for the other controller.
Note that you are instantiating each controller in ViewState, so just give that class access to each of the other models it may need.
Finally, you boot all this up with
public class MyApp extends Application {
#Override
public void start(Stage primaryStage) {
ViewState viewState = new ViewState(/* pass models here...*/);
viewState.showLogIn();
Scene scene = new Scene(viewState.currentViewProperty().get());
scene.rootProperty().bind(viewState.currentViewProperty());
primaryStage.setScene(scene);
primaryStage.show();
}
}
Can I bind stage.getUserData with TextBox?
My goal is.
If user select my application I save information in method start stage.setUserData in event focusesProperty.
public void start(Stage stage) throws Exception {
try{
Parent root = FXMLLoader.load(getClass().getResource("Hlavni.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.getIcons().add(new Image("file:kcl.gif"));
stage.setTitle("KCL - Evidence hovorů - v1.0");
stage.show();
/*
Implementujeme událost - stav kdy uživatel vybere okno aplikace.
*/
stage.focusedProperty().addListener((ObservableValue<? extends Boolean> ov, Boolean lostFocus, Boolean gainFocus) -> {
if (gainFocus==true) {
try {
/*
Po výběru gainFocus naplníme systémovou metodu stage.setUserData
V kontroleru dané vyzvědneme přes zjištěnou stage.getUserData
Do metody ukládáme, pouze pokud je null
*/
// Pokud je stage.getUserData == null, uložíme tam číslo, jinak nic.
if(stage.getUserData() == null){
// Připojíme se do MSSQL a zjistíme telefonní číslo
stage.setUserData("607700962");
}
}catch(Exception e){
e.printStackTrace();
}
}
});
In controller I need to fill automatically TextBox.
There for I have idea bind stage.getUserData with TextBox.
I would just put a method in the controller class and call it:
e.g.
public class MyController {
// #FXML-annotated nodes from fxml file, e.g.
#FXML
private TextField textField ;
public void initialize() {
// ...
}
// handlers etc...
public void setInformation(String data) {
// update text box:
textField.setText(data);
}
}
and then you can just do
public void start(Stage stage) throws Exception {
try{
FXMLLoader loader = new FXMLLoader(getClass().getResource("Hlavni.fxml"));
Parent root = loader.load();
MyController controller = loader.getController();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.getIcons().add(new Image("file:kcl.gif"));
stage.setTitle("KCL - Evidence hovorů - v1.0");
stage.show();
stage.focusedProperty().addListener((ObservableValue<? extends Boolean> ov, Boolean lostFocus, Boolean gainFocus) -> {
if (gainFocus) {
controller.setInformation("607700962");
}
});
} catch (Exception exc) {
exc.printStackTrace();
}
// ...
}
I have created a chart bar, and I wish to change the bar color according to the name of values. It has two series one shows number of green values which should be green and the other one yellow. I have also created a css file, but first problem is a get unknown property error for -fx-bar-fill in css. Beside I do not know how to call the appropriate color after creating the series? I face this warning at the time:
Mar 23, 2015 8:50:02 AM com.sun.javafx.css.parser.CSSParser parse
WARNING: CSS Error parsing file:/home/iman/workspace/AddNodeDynamicly /bin/application/chart.css: Expected LBRACE at [1,9]
Here I create the chart
public class MostComputerizedController {
#FXML
private BarChart<String, Number> barChart;
#FXML
private CategoryAxis orgNameAxis;
#FXML
private NumberAxis yAxis;
private ObservableList<String> orgNames = FXCollections
.observableArrayList();
private DataConstructor dc = new DataConstructor();
#FXML
private void initialize() {
orgNames.addAll(dc.getSortedAssignedOrg().values());
orgNameAxis.setCategories(orgNames);
orgNameAxis.setLabel("Name of Organizations");
orgNameAxis.tickLabelFontProperty().set(Font.font(10));
yAxis.setLabel("Saturation");
orgNameAxis.getStylesheets().add(
getClass().getResource("/application/application.css").toExternalForm());
}
/*
* *
* Sets the organization to show the statistics for.
*
* #param
*/
public void setPersonData() {
XYChart.Series<String, Number> series = new XYChart.Series<>();
XYChart.Series<String, Number> seriesy = new XYChart.Series<>();
series.setName("Green");
seriesy.setName("Yellow");
for (String entryOrg : dc.getSortedAssignedOrg().values()) {
for (List<String> entryfuncType : dc.getFuncTypeOrg().values()) {
if (entryOrg.equals(entryfuncType.get(5))
&& entryfuncType.contains("hasType")) {
int yellow = Collections.frequency(entryfuncType, "yellow");
int green = Collections.frequency(entryfuncType, "Green");
int typeNumber = Collections.frequency(entryfuncType,
"hasType");
series.getData().add(
new XYChart.Data<String, Number>(entryOrg, green));
seriesy.getData().add(
new XYChart.Data<String, Number>(entryOrg, yellow));
}
}
}
barChart.getData().addAll(series,seriesy);
}
}
In main I add it to stage:
public class Main extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
private Model model = new Model();
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("IT-Saturation");
initRootLayout();
showOverView();
}
private void showOverView() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("/view/OverView.fxml"));
loader.setController(new OverViewController(model));
AnchorPane overView = (AnchorPane) loader.load();
rootLayout.setCenter(overView);
} catch (IOException e) {
e.printStackTrace();
}
}
private void initRootLayout() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("/view/RootLayout.fxml"));
loader.setController(new RootLayoutController(model));
rootLayout = (BorderPane) loader.load();
// show scene containing the root layout
Scene scene = new Scene(rootLayout);
scene.getStylesheets().add(
getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
RootLayoutController controller = loader.getController();
controller.setMainApp(this);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
public void showMostComputerizedStatistics() {
try {
// Load the fxml file and create a new stage for the popup.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class
.getResource("/view/MostComputerized.fxml"));
AnchorPane page = (AnchorPane) loader.load();
Stage dialogStage = new Stage();
dialogStage.setTitle("Saturation in Organizations");
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(primaryStage);
Scene scene = new Scene(page);
dialogStage.setScene(scene);
dialogStage.getScene().getStylesheets().add(
getClass().getResource("chart.css").toExternalForm());
MostComputerizedController controller = loader.getController();
controller.setPersonData();
dialogStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
and this is the css file:
#CHARSET "UTF-8";
.default-color0.chart-bar {
-fx-bar-fill: green;
}
.default-color1.chart-bar {
-fx-bar-fill: yellow;
}
If could get rid of the css warning by using -fx-background-color instead
.default-color0.chart-bar { -fx-background-color: rgb(146,208,80); }