2016-02-29 56 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(); 
} 


} 
} 

我把大多數代碼從教程,並定製適合您的解決方案。它有三種類型的反彈,但如果你稍微思考一下,你可以看到它們如何在使用主類的控制器之間進行通信以促進它。我沒有測試這個,但它應該非常接近你所需要的。