2016-02-29 58 views
0

我正在构建天气应用程序。有2个场景和2个控制器文件。一个是主屏幕,另一个是“设置”。主FXML包含一个标签,如果用户不想看到额外的信息,就必须在设置页面打开/关闭该标签。我的问题是如何从设置页面的控制器类设置可见标签,如果可能的话。 感谢您的帮助从其控制器外部访问节点JavaFX - MVC

+0

两个FXML文件之间的关系是什么? (例如,你什么时候显示设置页面?)你不应该暴露控制器外部的节点,但要么把功能放在你可以调用的控制器中来控制UI的状态,要么(更好地)在两个控制器之间共享一个模型,修改/观察其中的数据。你需要展示更多关于你如何为任何人设置事物的细节(或者至少对我来说:其他人可能更具透彻性......)能够提供帮助。 –

+0

詹姆斯D是对的。如果您直接在控制器中存储更改此可见性,则很难从其他来源获取数据(例如设置文件)。您最好将设置存储在模型中。 – fabian

回答

1

我假设只有在用户单击主屏幕上的按钮时才会出现设置场景。我最近不得不在我的代码中处理相同的情况。这里是处理这种情况的一个伟大的教程:

http://code.makery.ch/library/javafx-2-tutorial/part1/

1)在你MainScene控制器,你会引用主类,并调用其功能,弹出设置场景。

2)在主类中,你将有弹出的设置场景

3)设置场景后关闭的功能,将通过主类传递值回MainScene控制器和根据返回值您可以设置标签。

1.)您的主场景的MainController将具有对主类的引用以及通过主类调用设置场景的函数。

public class MainController { 

@FXML 
private Label label; 
@FXML 
private Button Settings; 


// Reference to the main application 
private MainApp mainApp; 

/** 
* The constructor. 
* The constructor is called before the initialize() method. 
*/ 
public MainController() { 
} 

/*Tie this function to your button that pops up Settings */ 

private void handleSettingsButton() { 

     /* Here you call a function in the main class and pass the label 
     * to the settings scene controller */ 

     boolean show = mainApp.showSettingsScene(label); 
     if (show) { 
       label.isVisible("True"); 
     } 
     else { 
       label.isVisible("False"); 
     } 
} 

/** 
* Is called by the main application to give a reference back to itself. 
* 
* @param mainApp 
*/ 
public void setMainApp(MainApp mainApp) { 
    this.mainApp = mainApp; 


} 
} 

2)在您的主类(不要与你的主场景相混淆)加载主场景,并调用setMainApp功能,让您的控制器的引用回到主类。

public class MainApp extends Application { 

private Stage primaryStage; 
private BorderPane rootLayout; 

@Override 
public void start(Stage primaryStage) { 
    this.primaryStage = primaryStage; 
    this.primaryStage.setTitle("Main"); 

/*Right when the app is loaded the MainScene shows up.*/ 

    try { 
     // Load the root layout from the fxml file 
     FXMLLoader loader = new FXMLLoader(MainApp.class.getResource("view/MainScene.fxml")); 
/* Get a reference to the controller instance of the main Scene */ 
mainSceneController = loader.getController(); 
    /*Allow the controller to talk to the main class */ 
    mainSceneController.setMainApp(this); 
     rootLayout = (BorderPane) loader.load(); 
     Scene scene = new Scene(rootLayout); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } catch (IOException e) { 
     // Exception gets thrown if the fxml file could not be loaded 
     e.printStackTrace(); 
    } 


} 

/** 
* Returns the main stage. 
* @return 
*/ 
public Stage getPrimaryStage() { 
    return primaryStage; 
} 

/*This function referenced in your main controller will show the Settings 
*Scene and wait to see what the user has selected for the visible or not 
*visible selection. We need to pass the label to it as well, so we 
*accurately load the Settings Scene with the current state of the label 
*/ 

public boolean showSettingsScene(Label label) { 
    try { 
     // Load the fxml file and create a new stage for the popup 
    FXMLLoader loader = new FXMLLoader(MainApp.class.getResource("view/SettingsScene.fxml")); 
settingsSceneController = loader.getController(); 

    /* Here we send the label to the controller instance of the Settings 
    * Scene */ 

    controller.setLabel(label); 
    AnchorPane page = (AnchorPane) loader.load(); 
    Stage dialogStage = new Stage(); 
    dialogStage.setTitle("Settings"); 
    dialogStage.initModality(Modality.WINDOW_MODAL); 
    dialogStage.initOwner(primaryStage); 
    Scene scene = new Scene(page); 
    dialogStage.setScene(scene); 

/* Show the dialog and wait until the user closes it*/ 
dialogStage.showAndWait(); 

/*Return the value that the user has selected for visible or not */ 
return controller.isShowOrHide(); 

    } catch (IOException e) { 
// Exception gets thrown if the fxml file could not be loaded 
e.printStackTrace(); 
    return false; 
    } 
} 

public static void main(String[] args) { 
    launch(args); 
} 
} 

3)中的设置场景控制器看起来类似以下内容:

import... 
public class SettingsSceneController{ 

@FXML private ComboBox showOrHide; 

private Stage dialogStage; 
private Boolean show = false; 
private Label label; 

/** 
* Initializes the controller class. This method is automatically called 
* after the fxml file has been loaded. 
*/ 
@FXML 
private void initialize() { 
    ;I don't know what you have, but if you use a Combobox... 
    showOrHide.getItems().addAll(
      "Show", 
      "Hide",); 

} 

/** 
* Sets the stage of this dialog. 
* @param dialogStage 
*/ 
public void setDialogStage(Stage dialogStage) { 
    this.dialogStage = dialogStage; 
} 

/*The label that was passed from Main Scene Controller to Main Class to 
* here is now used in the function to update the Combobox with the 
* current status of the label */ 
public void setLabel(Label label) { 
    this.label = label; 
    if(label.isVisible){ 
      showOrHide.setValue("Show"); 
      show = true; 
    } 
    else{ 
      showOrHide.setValue("Hide"); 
      show = false; 
    } 
} 



/** 
* Returns true if the user clicked OK, false otherwise. 
* @return 
*/ 
public boolean isShowOrHide() { 
    return show; 
} 

/** 
* Called when the user clicks ok. Attach this in Scene Builder,to the OK, 
* Enter or Apply or whatever you called it button of the Settings Scene 
* It will reflect any change made to the combobox. 
*/ 
@FXML 
private void handleOk() { 
    if (showOrHide.getValue().toString() == "Show") { 
     show= true; 
    } 
    else{ 
     show = false; 
    } 
     dialogStage.close(); 

} 

/** 
* Called when the user clicks cancel if you have a cancel button. 
*/ 
@FXML 
private void handleCancel() { 
    dialogStage.close(); 
} 


} 
} 

我把大多数代码从教程,并定制适合您的解决方案。它有三种类型的反弹,但如果你稍微思考一下,你可以看到它们如何在使用主类的控制器之间进行通信以促进它。我没有测试这个,但它应该非常接近你所需要的。