Passing a global ObservableList between 2 classes - java

I have a question. How can i pass the same reference of one ObservableList between two classes? I need to add an Element from my SimultanTestController to the List in FXMLDocumentController.
My Code (FXMLDocumentController):
public class FXMLDocumentController implements Initializable {
Stage primaryStage = new Stage();
Stage options = new Stage();
Stage selectTest = new Stage();
ObservableList<DefaultTestInterface> items = FXCollections.observableArrayList();
public ObservableList<DefaultTestInterface> getList() {
return items;
}
#FXML
private ListView ItemList;
#FXML
public Button btn_globalOptions;
#FXML
private Button btn_add;
#FXML
private Button btn_delete;
#FXML
private Button btn_moveUP;
#FXML
private Button btn_moveDOWN;
public void getPrimaryStage(Stage stage){
this.primaryStage=stage;
}
My Code (SimultanTestController):
public class SimultanTestController implements Initializable {
ObservableList<DefaultTestInterface> items = (new FXMLDocumentController()).getList();
#FXML
Button btn_ok;
public void addTest(ActionEvent event){
for( int x = 0 ; x < items.size() ; x++ ) { // start from index 0
System.out.println("Item" +items.get(x));
}
}
#Override
public void initialize(URL url, ResourceBundle rb) {
btn_ok.setOnAction(this::addTest);
}
}
So you see, i have one Method: getList
and this method is called in SimultanTestController and i try to parse the value of getList to the ObservableList in SimultanTestController.
After that, i want to to add an element to the ObservableList in FXMLDocumentController from SimultanTestController. But i dont get the same list in both classes ...
Thank you for help!
I load my FXML-Files in this class:
First i create all new stages for my FXML-Files and have 3 ObservableList with the FXML-File-Names, the window-titel and all the stages. Then i load all stages with my for-loop. (By the way, is this a good solution?)
My window opening way: Main-->SelectTest-->SimultanTest
public class SelectTestController implements Initializable {
ObservableList<String> items =FXCollections.observableArrayList();
Stage primaryStage = new Stage();
Stage simultan = new Stage();
Stage audioLoop = new Stage();
Stage cpu = new Stage();
Stage driversCD = new Stage();
Stage driversHD = new Stage();
Stage driversFD = new Stage();
Stage externalProgramm = new Stage();
Stage graphics = new Stage();
Stage interactive = new Stage();
Stage mainboard = new Stage();
Stage memorySPD = new Stage();
Stage memory = new Stage();
Stage network = new Stage();
Stage ports = new Stage();
Stage reboot = new Stage();
Stage signal = new Stage();
Stage userMessage = new Stage();
#FXML
private ListView lv_selectTest;
#FXML
private Button btn_choose;
#FXML
private Label test;
public void getPrimaryStage(Stage stage){
this.primaryStage=stage;
}
ObservableList<Stage> stages =FXCollections.observableArrayList();
ObservableList<String> fxml =FXCollections.observableArrayList();
ObservableList<String> stageTitel =FXCollections.observableArrayList();
public void initWindows(){
try {
for(int i=0;i<=stages.size();i++){
Window parent = primaryStage;
Parent root = FXMLLoader.load(getClass().getResource(fxml.get(i)));
Scene scene = new Scene(root);
stages.get(i).initOwner(parent);
stages.get(i).initModality(Modality.APPLICATION_MODAL);
stages.get(i).setTitle(stageTitel.get(i));
stages.get(i).setScene(scene);
stages.get(i).setResizable(false);
stages.get(i).setAlwaysOnTop(true);
}
}catch (IOException|IllegalStateException ex) {
System.out.println(ex);
}
}
I tried to get the controller of the FXML-Loader and this works. I get the value from JavaFX-Start methode and parse it to FXMLDocumentController. Now i have a var with the controller instance in my FXMLDocumentConroller. But i am not able to get the value in SimultanTest ot add something to the ObservableList items. I tired per new Instance() and setter+getter... I dont know why i dont get it...
It would be very nice if someone could give me an example based of my code ... You see i worked for my solution but im not getting further...

i found an own solution for my Problem. I dont get the Controller of FXMLMain, but i solved it with an Singelton Class which stores the ObservableList items.
Now i can set Items from every class and can show them in ListView in FXMLDocumentController. If some one have the same Problem, connect me for a solution.
Thanks for help # James_D

Related

Create two buttons next to each other in JavaFX

I'd like to create two buttons in the bottom of the window, one on the far left and the other one on the right. I'm using BorderPane and AnchorPane. When running only one button is displayed, because I call the method BorderPane.setBottom()two times, the first call is executed, the second one is not atleast not in a way I'd like it to. Is there a way to do this using BorderPane? I've only seen help for other versions.
BorderPane root = new BorderPane();
AddArea addArea = new AddArea();
DeleteArea deleteArea = new DeleteArea();
root.setBottom(deleteArea.getPane());
root.setBottom(addArea.getPane());
public class AddArea {
private final AnchorPane anchorPane = new AnchorPane();
private final Button addButton = new Button("Add");
public AddArea() {
AnchorPane.setBottomAnchor(addButton, 10.0);
AnchorPane.setLeftAnchor(addButton, 10.0);
anchorPane.getChildren().addAll(addButton);
}
public Node getPane() {
return anchorPane;
}
}
public class DeleteArea {
private final AnchorPane anchorPane = new AnchorPane();
private final Button deleteButton = new Button("Delete");
public DeleteArea() {
AnchorPane.setBottomAnchor(deleteButton, 10.0);
AnchorPane.setRightAnchor(deleteButton, 10.0);
anchorPane.getChildren().addAll(deleteButton);
}
public Node getPane() {
return anchorPane;
}
}
Thank you in advance!

How to remove flickering of main window at the beginning of a video in Javafx?

I'm making the application with JavaFX and Scene Builder. I have a fullscreen video before my appliaction start. SO it is a kind of intro for my appliaction.
A video has the same background as my main stage.
The problem is I have flickering effect at the very beginning when I launch the appliaction. Buttons and text from main window appear during like half of a second and then my video start.
How can I remove or hide that effect?
Please, check this link for more clear understanding of my problem
Video
Main Class:
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("fxml/card.fxml"));
Parent root = (Parent) loader.load();
Scene scene = new Scene(root, 1600, 600);
primaryStage.setScene(scene);
scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.setMaximized(true);
primaryStage.setResizable(true);
primaryStage.getIcons().add(new Image("logo-icon.png"));
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Controller where I place All buttons and text. I also have a video here:
public class Controller implements Initializable {
#FXML private AnchorPane mainAnchor, anchorRow, randomCard, randomCardBack, previewCard, bolt1;
#FXML private StackPane hBoxCat0;
#FXML private Button btnPalette, btnFont, btnQuestCards, btnNonQuestCards;
#FXML private ToggleButton btnPref1, btnPref2, btnPref3, btnPref4, btnPref5, btnPref6, btnPref7, btnPref8;
#FXML private Label lb_randomCard, lb_randomCardBack, answerID, lb_previewCard, category1, category2, category3, category4, category5, category6, category7, category8;
#FXML private ToggleGroup group;
#FXML private JFXColorPicker colorPickerCategory;
#FXML private Rectangle rectRandom, rectRandomBack;
#FXML private MediaView media;
private MediaPlayer mp;
private static final String MEDIA_URL = "intro.mp4";
#FXML
public void initialize(URL location, ResourceBundle resources) {
mp = new MediaPlayer(new Media(this.getClass().getResource(MEDIA_URL).toExternalForm()));
media.setMediaPlayer(mp);
media.setSmooth(true);
mp.setAutoPlay(true);
Timeline tm = new Timeline(new KeyFrame(Duration.millis(3000), new KeyValue(media.opacityProperty(), 0.0)));
tm.setDelay(Duration.millis(5500));
tm.play();
addQuestionsToArrayCat1();
addAnswersToArrayCat1();
addSentencesToArray();
matchSentences();
}
}

JavaFX not loading GUI

When I run my code in Eclipse the java window opens but there is no GUI from JavaFX. I have checked the console in Eclipse and there are no errors there.
I have even gone as far as to rewrite the project in a different directory but I get the same result.
How can I fix this?
Main.java
package application;
import javafx.application.Application;
public class Main extends Application {
public void start(Stage primaryStage) {
try {
FXMLLoader.load(getClass().getResource("/application/Main.fxml"));
BorderPane root1 = new BorderPane();
Scene scene = new Scene(root1,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
MainController.java
package application;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
public class MainController implements Initializable {
#FXML private TableView<Product> table;
#FXML private TableColumn<Product, String> Code;
#FXML private TableColumn<Product, String> Brand;
#FXML private TableColumn<Product, String> Type;
#FXML private TableColumn<Product, String> Colour;
#FXML private TableColumn<Product, String> Size;
#FXML private TableColumn<Product, Integer> Quantity;
public ObservableList<Product> list = FXCollections.observableArrayList(
new Product ("GD05", "Gildan", "T-Shirt", "Black", "Medium", 10),
new Product ("GD05", "Gildan", "T-Shirt", "Black", "Large", 5),
new Product ("GD05", "Gildan", "T-Shirt", "Black", "X Large", 3),
new Product ("GD05", "Gildan", "T-Shirt", "Black", "XX Large", 1)
);
#Override
public void initialize(URL location, ResourceBundle resources) {
Code.setCellValueFactory(new PropertyValueFactory<Product, String>("Code"));
Brand.setCellValueFactory(new PropertyValueFactory<Product, String>("Brand"));
Type.setCellValueFactory(new PropertyValueFactory<Product, String>("Type"));
Colour.setCellValueFactory(new PropertyValueFactory<Product, String>("Colour"));
Size.setCellValueFactory(new PropertyValueFactory<Product, String>("Size"));
Quantity.setCellValueFactory(new PropertyValueFactory<Product, Integer>("Quantity"));
table.setItems(list);
}
}
It is loading the GUI: it's just not displaying it, because you don't ask it to.
public void start(Stage primaryStage) {
try {
// loads the FXML, but discards the result:
FXMLLoader.load(getClass().getResource("/application/Main.fxml"));
// creates a new, empty BorderPane
BorderPane root1 = new BorderPane();
// makes the empty border pane the root of the scene:
Scene scene = new Scene(root1,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
// sets the scene in the stage and shows it:
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
You need something like:
public void start(Stage primaryStage) {
try {
BorderPane root1 = FXMLLoader.load(getClass().getResource("/application/Main.fxml"));
Scene scene = new Scene(root1,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
This assumes the root element of your FXML file is a BorderPane, which I'm guessing is the intention here. If not, you can either change BorderPane to the relevant type, or you can do
BorderPane root1 = new BorderPane();
root1.setCenter(FXMLLoader.load(...));
The value of the below has to be put in
a container.
FXMLLoader.load(getClass().getResource("/application/Main.fxml"));
Like
BorderPane root1;
root1 = FXMLLoader.load(getClass().getResource("/application/Main.fxml"));

How to add JavaFX Preloader ProgressBar on top of an FXML scene

I am new to Java and JavaFX all together, so please be patient with me if I am asking the wrong question here.
I am trying to add preloader Scene to an application I built: I was able to add the preloader using the code below. It's the default preloader and it looks very basic. So, here is my question. 1) how to add percentage progress status instead of progressbar. 2) Is it possible to load this progress bar on top of an FXML scene
Preloader
public class JavaFXPreloader3 extends Preloader {
ProgressBar bar;
Stage stage;
private Scene createPreloaderScene() throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("FXML.fxml"));
ProgressIndicator pi = new ProgressIndicator();
BorderPane p = new BorderPane();
p.setCenter(pi);
return new Scene(p, 300, 150);
}
#Override
public void start(Stage stage) throws Exception {
this.stage = stage;
stage.setScene(createPreloaderScene());
stage.show();
}
#Override
public void handleStateChangeNotification(StateChangeNotification scn) {
if (scn.getType() == StateChangeNotification.Type.BEFORE_START) {
stage.hide();
}
}
#Override
public void handleProgressNotification(ProgressNotification pn) {
bar.setProgress(pn.getProgress());
}
}
How do I return root scene instead of the BorderPane p including the Progress Indicator:
ProgressIndicator pi = new ProgressIndicator();
BorderPane p = new BorderPane();
p.setCenter(pi);
return new Scene(p, 300, 150);
This is a excellent tutorial for creating a PreLoader.
https://docs.oracle.com/javafx/2/deployment/preloaders.htm

How to swtich to new scene in the same stage JavaFX

I try to switch between scenes in same stage. I'm beginner in JavaFX so I don't know how to do it easily without spaghetti code. When I start code below I get null pointer at rootLayout.setCenter(content) in showCarChoosePage method (second scene). I know rootLayout is null and I was trying create new scene with and load it to primaryStage but then I got null pointer too. showCarChoosePage method is calling from LoginController. Thanks for your help
public class MC extends Application {
public Scene scene;
private GridPane grid;
public AnchorPane content;
public BorderPane rootLayout;
public Stage primaryStage;
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("VMHT v0.1");
try {
FXMLLoader loader = new FXMLLoader(MC.class.getResource("view/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
showLoginPage();
//showCarChoosePage();
}
public void showLoginPage(){
try {
FXMLLoader loader = new FXMLLoader(MC.class.getResource("view/LoginView.fxml"));
content = (AnchorPane) loader.load();
rootLayout.setCenter(content);
LoginController controller = loader.getController();
controller.setMC(this);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void showCarChoosePage(){
try {
FXMLLoader loader = new FXMLLoader(MC.class.getResource("view/CarChooseView.fxml"));
AnchorPane content = (AnchorPane) loader.load();
rootLayout.setCenter(content);
CarChooseController controller = loader.getController();
controller.setMC(this);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Here is another way to handle multiple scenes. It uses Controllers for each scene. You must pass the initial stage that was created in Main to each new Controller. You must also pass whatever data you want to share from Controller to Controller. This is all done with methods that are added to your controllers.
In this simple case a Person object was created with name, sex, and age class variables as well as setters and getters for these objects.
Then I created 3 fxml files (using SceneBuilder) that displayed the name, sex, and age values. Of course, I also created 3 controllers, one for each fxml file.
The user was allowed to edit these values. One scene allowed name entry, another allowed sex entry, and the last allowed age entry. This simulated a complex app where data entry and processing was divided among 3 different scenes.
The three fxml files and the 3 controllers look very similar to one another. Here is the NameController. It first has setters for the Stage and Person objects. It also has button event handlers to allow the user to navigate to the other stages.
package multiscene;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import java.net.URL;
import java.util.ResourceBundle;
public class NameController implements Initializable {
#FXML private TextField lblSex;
#FXML private TextField lblAge;
#FXML private TextField txtName;
private Stage myStage;
private Person person;
public void setStage(Stage myStage) {
this.myStage = myStage;
}
public void setPerson(Person person) {
this.person = person;
lblAge.setText(person.getAge());
txtName.setText(person.getName());
lblSex.setText(person.getSex());
}
#FXML
private void ageClicked(ActionEvent event) throws Exception{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(NameController.class.getResource("Age.fxml"));
AnchorPane page = (AnchorPane) loader.load();
Stage dialogStage = new Stage();
dialogStage.setTitle("Person Editor");
// dialogStage.initModality(Modality.WINDOW_MODAL);
//dialogStage.initOwner(primaryStage);
Scene scene = new Scene(page);
dialogStage.setScene(scene);
// Set the person into the controller
person.setName(txtName.getText());
AgeController newController = loader.getController();
newController.setStage(dialogStage);
newController.setPerson(person);
dialogStage.show();
myStage.close();
}
#FXML
private void sexClicked(ActionEvent event) throws Exception {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(AgeController.class.getResource("Sex.fxml"));
AnchorPane page = (AnchorPane) loader.load();
Stage dialogStage = new Stage();
dialogStage.setTitle("Person Editor");
// dialogStage.initModality(Modality.WINDOW_MODAL);
//dialogStage.initOwner(primaryStage);
Scene scene = new Scene(page);
dialogStage.setScene(scene);
// Set the person into the controller
person.setName(txtName.getText());
SexController newController = loader.getController();
newController.setStage(dialogStage);
newController.setPerson(person);
dialogStage.show();
myStage.close();
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
Main.java must initialize the Stage and the shared data as follows. Both the Stage and the shared data are passed to the first Scene when it is loaded.
package multiscene;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Person person = new Person();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("Name.fxml"));
AnchorPane page = (AnchorPane) loader.load();
Stage dialogStage = new Stage();
dialogStage.setTitle("Person Editor");
Scene scene = new Scene(page);
dialogStage.setScene(scene);
NameController nameController = loader.getController();
nameController.setStage(dialogStage);
nameController.setPerson(person);
dialogStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Here is one simple method you might try
import javafx.stage.Stage;
public class ManyScenes extends Application {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(final Stage primaryStage) {
primaryStage.setTitle("Hello World");
Group root1 = new Group();
Group root2 = new Group();
Group root3 = new Group();
final Scene scene1 = new Scene(root1, 300, 250);
final Scene scene2 = new Scene(root2, 300, 250);
final Scene scene3 = new Scene(root3, 300, 250);
Button go1 = new Button();
go1.setLayoutX(100);
go1.setLayoutY(80);
go1.setText("Go to scene2");
go1.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
primaryStage.setScene(scene2);
}
});
root1.getChildren().addAll(new Label("Scene 1"), go1);
Button go2 = new Button();
go2.setLayoutX(100);
go2.setLayoutY(80);
go2.setText("Go to scene3");
go2.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
primaryStage.setScene(scene3);
}
});
root2.getChildren().addAll(new TextField(), go2);
Button go3 = new Button();
go3.setLayoutX(100);
go3.setLayoutY(80);
go3.setText("Back to scene1");
go3.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
primaryStage.setScene(scene1);
}
});
root3.getChildren().addAll(new TextArea(), go3);
primaryStage.setScene(scene1);
primaryStage.show();
}
}

Categories