please help me.
I have following code.
public class Main extends Application {
private static Locale locale = new Locale("de", "DE");
private Scene scene;
public static Stage stage;
#Override
public void start(Stage primaryStage) throws Exception {
stage = primaryStage;
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
ResourceBundle bundle = ResourceBundle.getBundle("bundles.lang", locale);
fxmlLoader.setResources(bundle);
Parent root = fxmlLoader.load();
scene = new Scene(root);
stage.setMaximized(true);
stage.setScene(scene);
stage.show();
}
public void reload() throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
fxmlLoader.setResources(ResourceBundle.getBundle("bundles.lang", locale));
Parent root = fxmlLoader.load();
scene = new Scene(root);
stage.setMaximized(true);
stage.setScene(scene);
stage.show();
}
}
in my Controller class
public class FXMLDocumentController implements Initializable {
#FXML
AnchorPane root;
#FXML
private void handleChinese(final ActionEvent event) throws IOException {
Main.setLocale(new Locale("zh", "CN")); // change to english
//JavaFXApplication4.stage.close();
Main reload = new Main();
reload.reload();
}
#FXML
private void handleRussian(final ActionEvent event) throws IOException {
Main.setLocale(new Locale("de", "DE")); // change to english
Main reload = new Main();
reload.reload();
}
it works!, but when change language my window did not show correctly, it means stage.setMaximized(true) did not work, my window did not show as Maximized.
Why does stage.setMaximized(true) not work correctly?
Instead of creating a new scene , just set root to the previous scene.
public void reload() throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
Parent root = fxmlLoader.load();
stage.getScene().setRoot(root);
// Scene scene = new Scene(root);
// stage.setMaximized(true);
// stage.setScene(scene);
//
// stage.show();
}
Related
Departments controllers are loaded from SceneWithButtonsController. StageAddController is loaded from LayoutWithHomeAndAddController. I want to execute this method from StageAddController which executes corresponding method from departments controller :
//Show Stage to add a worker
public class LayoutWithHomeAndAddController {
#FXML
private void addButtonClicked() throws IOException{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/views/StageAdd.fxml"));
BorderPane addWorkerPane = loader.load();
StageAddController stageAddController = loader.getController();
Stage stageAdd = new Stage();
stageAdd.setTitle("Add New Worker");
stageAdd.resizableProperty().setValue(Boolean.FALSE);
Scene scene = new Scene(addWorkerPane);
scene.getStylesheets().add("/css/redBorder.css");
stageAdd.setScene(scene);
stageAdd.initModality(Modality.WINDOW_MODAL);
Stage mainStage = (Stage) root.getScene().getWindow();
stageAdd.initOwner(mainStage);
stageAdd.show();}
}
Controller class where departments are loaded:
public class SceneWithButtonsController {
//Show workers from Mechanical Department
#FXML
private void mechanicalDepartmentButtonClicked() throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("/views/MechanicalDepartment.fxml"));
BorderPane mehOdjel = loader.load();
MechanicalDepartmentController mechanicalDepartmentController = loader.getController();
mechanicalDepartmentController.populateTable();
BorderPane borderPane = (BorderPane) pane.getParent();
borderPane.setCenter(mehOdjel);
}
//Show workers from Electrical Department
#FXML
private void electricalDepartmentButtonClicked() throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("/views/ElectricalDepartment.fxml"));
BorderPane elOdjel = loader.load();
ElectricalDepartmentController electricalDepartmentController = loader.getController();
electricalDepartmentController.populateTable();
BorderPane borderPane = (BorderPane) pane.getParent();
borderPane.setCenter(elOdjel);
}
}
StageAddController:
public class StageAddController {
private ElectricalDepartmentController electricalDepartmentController;
private MechanicalDepartmentController mechanicalDepartmentController;
public void setElectricalDepartmentController(ElectricalDepartmentController electricalDepartmentController) {
this.electricalDepartmentController = electricalDepartmentController;
}
public void setMechanicalDepartmentController(MechanicalDepartmentController mechanicalDepartmentController) {
this.mechanicalDepartmentController = mechanicalDepartmentController;
}
public void refreshTableOnSaveButtonClicked() {
if (departmentBox.getValue().equals("Electrical")) {
electricalDepartmentController.refreshButtonClicked();
}
else if(departmentBox.getValue().equals("Mechanical")) {
mechanicalDepartmentController.refreshButtonClicked();
}
}
}
This means that refreshButtonClicked() method from ElectricalDepartmentController or MechanicalDepartmentController will be executed.
ElectricalDepartmentController (same is with MechanicalDepartmentController):
public class ElectricalDepartmentController {
public void initialize() throws IOException {
StageAddController stageAddController = new StageAddController();
stageAddController.setElectricalDepartmentController(this);
workersTableColumn.setCellValueFactory(new PropertyValueFactory<>("nameSurname"));
rowSelected();
}
#FXML
public void populateTable() {
for(Worker worker : workerDao.getWorkersNameSurname("Electrical")) workersList.addAll(worker);
workersTable.setItems(workersList);
}
#FXML
public void refreshButtonClicked() {
workersList.removeAll(workersList);
populateTable();
}
}
How to achieve this.
You need to link controllers. In order to do that, when loading the respective FXML for the subordinate form, you have to set the parent controller for it manually so that you can have access to it.
Unfortunately, FXML does not provide a native way to link controllers. What you want to do is you want to use the full FXMLLoader functionality (instead of using FXMLLoader.load()), since the FXMLLoader also has a getController() method. It's probably a wise idea for your controllers to implement something like this:
public interface HierarchicalController {
HierarchicalController getParentController();
void setParentController(HierarchicalController controller);
}
EDIT: Component preload code:
public class SceneWithButtonsController {
protected FXMLLoader<?> mechanicalLoader;
protected FXMLLoader<?> electricalLoader;
protected BorderPane mechanicalPane;
protected BorderPane electricalPane;
public void initialize() {
mechanicalLoader = new FXMLLoader(Main.class.getResource("/views/MechanicalDepartment.fxml"));
mechanicalPane = loader.load();
MechanicalDepartmentController mechanicalDepartmentController = loader.getController();
mechanicalDepartmentController.populateTable();
electricalLoader = new FXMLLoader(Main.class.getResource("/views/MechanicalDepartment.fxml"));
electricalPane = loader.load();
ElectricalDepartmentController electricalDepartmentController = loader.getController();
electricalDepartmentController.populateTable();
// now what is the relation between StageAddController and SceneWithButtonsController ?
}
//Show workers from Mechanical Department
#FXML
private void mechanicalDepartmentButtonClicked() throws IOException {
BorderPane borderPane = (BorderPane) pane.getParent();
borderPane.setCenter(mechanicalPane);
}
//Show workers from Electrical Department
#FXML
private void electricalDepartmentButtonClicked() throws IOException {
BorderPane borderPane = (BorderPane) pane.getParent();
borderPane.setCenter(electricalPane);
}
}
Sembako.java this Main class
public class Sembako extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("rootScene.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Login");
stage.setResizable(false);
stage.show();
}
rootSceneController.java
#FXML
private void loginAction(ActionEvent event) throws IOException {
for (indrian16.oulook.id.co.sembako.entity.Login l : listLogin) {
if(username.getText().equals(l.getUsername())) {
if(password.getText().equals(l.getPassword())) {
Parent rootDashBoard = FXMLLoader.load(getClass().getResource("dashboard.fxml"));
Stage stage = new Stage();
Scene scene = new Scene(rootDashBoard);
stage.setScene(scene);
stage.setTitle("Sembako");
stage.show();
stage.close(); //how close Sembako scene :)
} else {
msgLogin.setText("Password Invalid");
}
} else {
msgLogin.setText("Username Invalid");
}
}
}
how close window Sembako scene in rootSceneController.java
sorry my bad english
I think you are asking how to close the previously-opened window. Assuming this is the window containing the username text field, you can do
username.getScene().getWindow().hide();
I want to assign an existing handleModellAction method to a generated Hyperlink with the setOnAction method, but I don't know how to do this.
Here is my code example:-
#FXML
private void handleModellAction(ActionEvent event) throws IOException{
FXMLLoader load = new FXMLLoader(getClass().getResource("InEX.fxml"));
Parent root = (Parent) load.load();
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.show();
link = (Hyperlink) event.getTarget();
model = link.getId();
stage.setTitle(model);
}
public void addNeuesModell(String bauart, String modelName){
modelHyperlink = new Hyperlink();
modelHyperlink.setId(modelName);
modelHyperlink.setText(modelName);
modelHyperlink.setOnAction(#handleModellAction);
}
Does somebody know how to do this?
Thanks a lot :)
You could try to call the setOnAction method on the modelHyperlink and pass as parameter an anonymous class as a handler, where in you could transfer the logic of your handleModellAction method. Below you can find an example:
Hyperlink link = new Hyperlink();
link.setText("http://example.com");
link.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
FXMLLoader load = new
FXMLLoader(getClass().getResource("InEX.fxml"));
Parent root = (Parent) load.load();
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.show();
link = (Hyperlink) event.getTarget();
model = link.getId();
stage.setTitle(model);
}
});
instead of defining
<HyperLink fx:id="myLink" onAction="#handleModelAction"/>
you can use just:
<HyperLink fx:id="myLink"/>
Then in the code:
refactor your handleMethod like this:
private void handleModellAction() throws IOException {
FXMLLoader load = new FXMLLoader(getClass().getResource("InEX.fxml"));
Parent root = load.load();
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.show();
}
after that:
myLink.setOnAction(action -> {
try {
handleModellAction();
} catch (IOException e) {
e.printStackTrace();
}
});
Then you can use that handleModellAction() anywhere you want in any button, hyperlink and so on..
I have decided to update my application using JavaFXML, However I am having difficulties passing a scene into my controller. Here is my Controller;
public class MainApp extends Application {
#FXML
public Stage primaryStage;
#FXML
private AnchorPane rootLayout;
#FXML
private JobInterface jInterface;
#Override
public void start(Stage primaryStage) {
primaryStage = new Stage();
setPrimaryStage(primaryStage);
initRootLayout();
}
#FXML
public void initRootLayout(){
try {
primaryStage = getPrimaryStage();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("MainInterface.fxml"));
rootLayout = (AnchorPane) loader.load();
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
setPrimaryStage(primaryStage);
} catch (IOException e) {
e.printStackTrace();
}
}
#FXML
private void setJobLayout(){
primaryStage = getPrimaryStage();
jInterface = new JobInterface();
jInterface.initJobLayout();
primaryStage.setScene(jInterface.getScene());
}
public static void main(String[] args) {
launch(args);
}
public Stage getPrimaryStage() {
return primaryStage;
}
public void setPrimaryStage(Stage primaryStage) {
this.primaryStage = primaryStage;
}
}
Here is a method that is changing the scene using a different FXML file and attempting to pass the scene back to the controller;
public class JobInterface {
private AnchorPane rootLayout;
private Scene scene;
public void initJobLayout(){
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("JobInterface.fxml"));
rootLayout = (AnchorPane) loader.load();
scene = new Scene(rootLayout);
setScene(scene);
} catch (IOException e) {
e.printStackTrace();
}
}
public Scene getScene() {
return scene;
}
public void setScene(Scene scene) {
this.scene = scene;
}
}
The issue I'm having now is a NullPointerException on this line in the main app;
primaryStage.setScene(jInterface.getScene());
I am trying to pass a Stage between methods so that I can only update the Scene and not have to open a new Stage everytime a new method is called. Any ideas on where I am going wrong?
There should be no need to pass the stage or scene. Your Main will load the fxml resource which will have your fxml controller 'in charge' of your fxml file.
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("jobController.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
Your controller might look something like this (depending on your fxml design):
public class JobController {
#FXML
private Label label;
#FXML
private void handleButtonAction(ActionEvent event) {
label.setText("This is the controller speaking");
}
}
Now you can 'control' your stage (scene) from the controller. If you are going to create another class which also has to update the scene, pass a reference to the controller to it e.g. from the controller:
TimeClock timeClock = new TimeClock();
timeClock.init(this);
and then in TimeClock.java you have:
private final JobController controller;
public void init (JobController control){
this.controller = control;
}
Now you can access any public method in your controller from the TimeClock class. E.g.
controller.updateLabel("Time clock speaking!");
Working with SceneBuilder. I have 2 stages, each one with a controller: stage1Controller,stage2Controller.
Stage1Controller :
public class Stage1Controller {
#FXML
private MenuItem translate;
#FXML
private Menu file;
#FXML
private Menu edit;
#FXML
private Menu help;
#FXML
private void handleTranslate (ActionEvent event){
translateFirstStage();
//HOW TO ACCESS THE stage2Controller setLabel()??
}
private void translateFirstStage(){
file.setText("Fichier");
edit.setText("Modifier");
help.setText("Aide");
}
}
Stage2Controller:
public class Stage2Controller {
#FXML
private Label lb;
private void setLabel(String string){
lb.setText("string");
}
}
Here is how both fxml files are loaded in Main.java class using 2 methods (called in Start(Stage primaryStage) method):
public void firstStage() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/stage1.fxml"));
rootLayout = (BorderPane) loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public void secondStage() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/stage2.fxml"));
XD = (AnchorPane) loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(XD);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
The handleTranslate(ActionEvent event) method is used as an OnAction method for the MenuItem translate in the first Stage, it translates the view in both stages.
How Can i put setLabel in handleTranslate Method ? Thanks
The "quick and dirty" way is to give the Stage1Controller a reference to the Stage2Controller:
public class Stage1Controller {
private final Stage2Controller stage2Controller ;
public void setStage2Controller(Stage2Controller stage2Controller) {
this.stage2Controller = stage2Controller ;
}
// ...
#FXML
private void handleTranslate (ActionEvent event){
translateFirstStage();
stage2Controller.setLabel(...);
}
// other code as before ...
}
Now in your main app:
public class MainApp extends Application {
private Stage1Controller stage1Controller ;
private Stage2Controller stage2Controller ;
#Override
public void start(Stage primaryStage) {
firstStage();
secondStage();
stage1Controller.setStage2Controller(stage2Controller);
// ...
}
public void firstStage() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/stage1.fxml"));
rootLayout = (BorderPane) loader.load();
stage1Controller = loader.getController();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public void secondStage() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/stage2.fxml"));
XD = (AnchorPane) loader.load();
stage2Controller = loader.getController();
// Show the scene containing the root layout.
Scene scene = new Scene(XD);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
// ...
}
A more robust approach to this, though, is to let both controllers access a shared model class, storing the data. If you represent the data using JavaFX observable properties, the controllers can listen for changes on the properties they care about. For example:
public class Model {
private final StringProperty text = new SimpleStringProperty("Initial text...");
public StringProperty textProperty() {
return text ;
}
public final void setText(String text) {
textProperty().set(text);
}
public final String getText() {
return textProperty().get();
}
// other properties as needed...
}
Now your controllers will look like this:
public class Stage1Controller {
private Model model ;
public void setModel(Model model) {
this.model = model ;
}
#FXML
private void handleTranslate (ActionEvent event){
translateFirstStage();
model.setText(...); // value will appear in stage2 controller's label!
}
// ...
}
and
public class Stage2Controller {
#FXML
private Label lb ;
private Model model ;
public void setModel(Model model) {
lb.textProperty().unbind();
this.model = model ;
lb.textProperty().bind(model.textProperty());
}
// ...
}
And in this case your main app looks like:
public class MainApp extends Application {
private final Model = new Model();
#Override
public void start(Stage primaryStage) {
// ...
}
public void firstStage() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/stage1.fxml"));
rootLayout = (BorderPane) loader.load();
Stage1Controller controller = loader.getController();
controller.setModel(model);
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public void secondStage() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("view/stage2.fxml"));
XD = (AnchorPane) loader.load();
Stage2Controller controller = loader.getController();
controller.setModel(model);
// Show the scene containing the root layout.
Scene scene = new Scene(XD);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
}