If I try to load a screen with a button called "vorige" it go's in an error.
This is the error I got :
I find it strange because the logout button works in exactly the same way and there is no error there. If I remove the onAction method in the FXML file the exception is gone.
Kind regards
Fietsschermcontroller
#FXML
private Button buVorige;
/**
* Initializes the controller class.
*/
public void setMain(Vivesbike main) {
this.main = main;
}
/**
*
* #param vorigeEvent
*/
public void Vorige(ActionEvent vorigeEvent){
main.loadBeginscherm();
}
Fietsscherm FXML
<Button fx:id="buVorige" layoutX="31.0" layoutY="23.0" mnemonicParsing="false" onAction="#Vorige" prefHeight="39.0" prefWidth="102.0" text="Vorige" />
This function is in the main
public void loadBeginscherm(){
try {
FXMLLoader loader = new FXMLLoader(this.getClass().getResource("view/Beginscherm.fxml"));
BeginschermController controller = new BeginschermController();
loader.setController(controller);
Parent root = loader.load();
controller.setMain(this);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.centerOnScreen();
stage.setTitle("Keuzescherm");
stage.show();
} catch (IOException ex) {
System.out.println("Fout tijdens het laden van het beginscherm: "+ex.getMessage());
}
}
public void loadFietsscherm(){
try {
FXMLLoader loader = new FXMLLoader(this.getClass().getResource("view/Fietsscherm.fxml"));
BeginschermController controller = new BeginschermController();
loader.setController(controller);
Parent root = loader.load();
controller.setMain(this);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.centerOnScreen();
stage.setTitle("Fietsscherm");
stage.show();
} catch (IOException ex) {
System.out.println("Fout tijdens het laden van het fietsscherm: "+ex.getMessage());
}
}
In the loadFietsscherm method you connect BeginschermController to Fietsscherm.fxml, but I'm sure FietsschermController is implied to be there.
Related
I want to make it so that when a button is pressed, different windows are displayed, and for this I need conditions. I don't want to create many methods for each button
This code doesn't work:
#Override
public void buttonOnAction(ActionEvent event){
if(btnReaders.isPressed()){
btnReaders.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
Parent parent = null;
try {
parent = FXMLLoader.load(getClass().getResource("readersMenu.fxml"));
} catch (IOException ex) {
ex.printStackTrace();
}
Scene scene = new Scene(parent);
Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow();
window.setScene(scene);
window.show();
}
});
}
else if(btnDashboard.isPressed()){
btnDashboard.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
Parent parent = null;
try {
parent = FXMLLoader.load(getClass().getResource("librarianMenu.fxml"));
} catch (IOException ex) {
ex.printStackTrace();
}
Scene scene = new Scene(parent);
Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow();
window.setScene(scene);
window.show();
}
});
}
}
Here is an example of a parameterized event handler that will open the selected FXML in a new scene that will be set for the same stage containing the source node of the event.
When the event handler is created, the application stores, in the event handler, the name of the FXML resource to be loaded.
The event handler is assigned to a button action.
When the button is actioned, the event handler loads a new FXML into a new scene and attaches that scene to the window that the button is defined in.
Example App
For this example, FXML files should be in the same location as the package containing the SceneSelector application.
SceneSelector.java
import javafx.application.Application;
import javafx.event.*;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.io.IOException;
import java.util.Objects;
public class SceneSelector extends Application {
#Override
public void start(Stage stage) {
Button sceneAButton = new Button("Scene A");
sceneAButton.setOnAction(
new SceneChangeEventHandler(
"sceneA.fxml"
)
);
Button sceneBButton = new Button("Scene B");
sceneBButton.setOnAction(
new SceneChangeEventHandler(
"sceneB.fxml"
)
);
Pane layout = new HBox(10,
sceneAButton,
sceneBButton
);
layout.setPadding(new Insets(10));
layout.setPrefSize(200, 150);
stage.setScene(
new Scene(layout)
);
stage.show();
}
class SceneChangeEventHandler implements EventHandler<ActionEvent> {
private final String fxmlResourceName;
public SceneChangeEventHandler(String fxmlResourceName) {
this.fxmlResourceName = fxmlResourceName;
}
#Override
public void handle(ActionEvent event) {
try {
Stage stage = (Stage) ((Node) event.getSource())
.getScene()
.getWindow();
changeScene(stage, fxmlResourceName);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void changeScene(
Stage stage,
String fxmlResourceName
) throws IOException {
Parent parent = FXMLLoader.load(
Objects.requireNonNull(
getClass().getResource(
fxmlResourceName
)
)
);
Scene scene = new Scene(parent);
stage.setScene(scene);
stage.setTitle(fxmlResourceName);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
sceneA.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<StackPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
prefHeight="150.0" prefWidth="200.0" style="-fx-background-color: lemonchiffon;"/>
sceneB.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<StackPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
prefHeight="150.0" prefWidth="200.0" style="-fx-background-color: azure;"/>
I want to create an app with a couple of different views (therefore I can change roots), however with the same toolbar (which after clicking certain buttons changes the root). So far I tried both hard-coding toolbar in fxtml files, as well as creating it in my main app (but the issue then is that I need to change scenes which don't contain toolbar any more). Right now my code looks like this:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
Parent bikeScene = FXMLLoader.load(getClass().getResource("bikes.fxml"));
Button bikes = new Button("Bikes");
bikes.getStylesheets().add("tool-bar");
bikes.setOnAction(e->primaryStage.setScene(new Scene(bikeScene, 900, 1900)));
ToolBar tb = new ToolBar();
tb.getItems().add(bikes);
primaryStage.setTitle("management app");
VBox vb = new VBox(tb);
Scene sc = new Scene(vb, 900, 1900);
sc.getStylesheets().add("sample/style.css");
primaryStage.setScene(sc);
primaryStage.setMaximized(true);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I know this is very bad, but I am pretty stuck and not sure how to incorporate both the root and the toolbar when creating a scene.
edit:
So I decided to have a mainView as my root and now I have:
public class Main extends Application {
public void start(Stage primaryStage) throws Exception{
Button bikes = new Button("Bikes");
bikes.getStyleClass().add("tool-bar");
Button rooms = new Button("Rooms");
rooms.getStyleClass().add("tool-bar");
Button food = new Button("Food");
food.getStyleClass().add("tool-bar");
Button cars = new Button("Cars");
cars.getStyleClass().add("tool-bar");
Button admin = new Button("Admin");
admin.getStyleClass().add("tool-bar");
BorderPane mainView = new BorderPane();
BorderPane ToolBorderPane = new BorderPane();
ToolBar tBarLeft=new ToolBar();
ToolBar tBarRight=new ToolBar();
tBarLeft.getItems().addAll(rooms, bikes, food, cars);
tBarRight.getItems().add(admin);
ToolBorderPane.setLeft(tBarLeft);
ToolBorderPane.setRight(tBarRight);
ToolBorderPane.getStyleClass().add("tool-bar");
mainView.setTop(ToolBorderPane);
bikes.setOnAction(e-> {
try {
mainView.getChildren().add(loader("bikes.fxml"));
} catch (IOException ex) {
ex.printStackTrace();
}
});
rooms.setOnAction(e-> {
try {
mainView.getChildren().add(loader("rooms.fxml"));
} catch (IOException ex) {
ex.printStackTrace();
}
});
food.setOnAction(e-> {
try {
mainView.getChildren().add(loader("food.fxml"));
} catch (IOException ex) {
ex.printStackTrace();
}
});
cars.setOnAction(e-> {
try {
mainView.getChildren().add(loader("cars.fxml"));
} catch (IOException ex) {
ex.printStackTrace();
}
});
admin.setOnAction(e->
{
try {
mainView.getChildren().add(loader("admin.fxml"));
} catch (IOException ex) {
ex.printStackTrace();
}
});
GridPane loader = loader("sample.fxml");
mainView.getChildren().add(loader);
primaryStage.setTitle("management app");
Scene sc = new Scene(mainView, 1900, 1900);
sc.getStylesheets().add("sample/style.css");
primaryStage.setScene(sc);
primaryStage.setMaximized(true);
primaryStage.show();
}
public GridPane loader(String string) throws IOException {
GridPane loader = FXMLLoader.load(getClass().getResource(string));
return loader;
}
public static void main(String[] args) {
launch(args);
}
}
In theory it somehow works, however after clicking on certain buttons I get really weirdly formatted content.
For instance, my rooms.fxml file looks as follows:
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
<Label alignment="BOTTOM_RIGHT" text="let's see if it works" />
</GridPane>
While the text appears on the left upper corner instead of bottom right.
I'm a newbie in JavaFX. I made a fx application it has a home and another jfxml file.
This is HomeContoler.java file for open another jfxmlfile
#FXML
public void actionIngredencesReg(ActionEvent event) {
try {
mainHome.setOpacity(0.2);
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Ingrdences.fxml"));
Parent root1 = (Parent) fxmlLoader.load();
Stage stage = new Stage();
stage.initModality(Modality.APPLICATION_MODAL);
stage.initStyle(StageStyle.UNDECORATED);
Scene scene = new Scene(root1);
stage.setScene(scene);
stage.show();
// mainHome.setOpacity(1);
} catch (Exception e) {
e.printStackTrace();
}
}
when I click on the menu items it will works likes
this the close code of Ingredients.fxml file
#FXML
Label close_label;
this is a label, here in action
#Override
public void initialize(URL url, ResourceBundle rb) {
close_label.setOnMouseClicked(e -> {
//this is code for close only science
Stage stage = (Stage) close_label.getScene().getWindow();
stage.close();
});
}
but after close Ingredients.fxml file home.fxml file be like this
[this is not needed for me][4]
I want to convert home.fxml file like this
as like this after closing the ingredient.fxml
i want to setOpcaity of home.fxml file into 1 after close the ingredient.fxml file
anyone can help me to fix it...
Just revert the opacity when the stage is hidden:
stage.setOnHidden(e -> mainHome.setOpacity(1));
In my JavaFX application I have to load many fxml files (200+) in the same time. I have decided to load them in background Task just like in https://stackoverflow.com/a/34878843 answear. Everything works fine (load time was acceptable) until JDK update. Newest version of JDK lengthened load time 3-4 times.
I have checked previous JDK releases and that problem appears from the JDK 8u92.
To test that issue I created new simple JavaFX FXML Application in Netbeans 8.1 and use only generated classes and fxml. Creating view from code works fine.
Application class:
public class FXMLLoaderTest extends Application {
private static Executor ex = Executors.newCachedThreadPool();
//private static Executor ex = Executors.newFixedThreadPool(400);
//private static Executor ex = Executors.newSingleThreadExecutor();
#Override
public void start(Stage stage) throws Exception {
VBox box = new VBox();
ScrollPane root = new ScrollPane(box);
Button b = new Button("GENERATE");
b.setOnAction(e -> {
IntStream.range(0, 1000).forEach(i -> {
Task<Parent> task = new Task<Parent>() {
#Override
protected Parent call() throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
Parent root = null;
try {
root = loader.load();
} catch (IOException ex) {
Logger.getLogger(Loader.class.getName()).log(Level.SEVERE, null, ex);
}
// StackPane root= new StackPane();
// Button click = new Button("Click");
// root.setPrefSize(300, 300);
// root.getChildren().add(click);
return root;
}
};
task.setOnSucceeded(ev -> {
final Parent parent = task.getValue();
box.getChildren().add(parent);
});
task.setOnFailed(ev -> task.getException().printStackTrace());
ex.execute(task);
});
});
box.getChildren().add(b);
Scene scene = new Scene(root, 400, 500);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
FXMLDocument.fxml
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fxmlloader.FXMLDocumentController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
</AnchorPane>
FXMLDocumentController.java
public class FXMLDocumentController implements Initializable {
#FXML
private Label label;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
I have tested this on several computers and result was always the same. On JDK 8u91 fxml files load fast. I have checked release note of 8u92 and I haven't found any changes in FXMLLoader class.
Has anybody encounter this issue? Mayby I am doing something wrong then please correct me.
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();
}
}