如何在Java FX中动态修改GridPane(或其他容器)中的Contol显示?

时间:2017-05-03 07:43:12

标签: javafx controls

我以一种新的方式看待这个问题:

我有一个简单的FXML应用程序,它有一个mainapp,一个控制器和一个视图。视图显示由三行组成的网格窗格,其中每行包含一个标签元素。所以gridpane对用户来说是这样的:

row 1
row 2
row 3

在用户选择行后,还会有一个名为“删除所选行”的按钮。单击该按钮时,会从网格窗格中临时删除或隐藏该元素。因此,如果选择了第2行并单击了该按钮,则用户将看到

row 1
row 3

上面的视图是使用Scene Builder创建的,它创建了一个名为AppOverview.fxml的XML文件。

有一个MainApp绘制具有以下代码的场景:

public class MainApp extends Application {
  private Stage primaryStage;
  private BorderPane rootLayout;  

  //Constructor
  public MainApp() {}

  @Override
  public void start(Stage primaryStage) 
  {
    this.primaryStage = primaryStage;
    primaryStage.initStyle(StageStyle.UNDECORATED);
    initRootLayout();
    showAppOverview();
  }

// Initializes the root layout.
  public void initRootLayout() {
    try {
      // Load root layout from fxml file.
      FXMLLoader loader = new FXMLLoader();
      loader.setLocation(MainApp.class.getResource("view/RootLayout.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) {

      System.out.println("Error in MainApp:initRootLayout()");
      System.exit(0);
    }
  }

  // Shows the app overview inside the root layout.
  public void showAppOverview() {
    try {
    // Load overview.
      FXMLLoader loader = new FXMLLoader();
      loader.setLocation(MainApp.class.getResource("view/AppOverview.fxml"));
      AnchorPane appOverview = (AnchorPane) loader.load();
      // Set overview into the center of root layout.
      rootLayout.setCenter(appOverview);
      // Give the controller access to the main app.
      AppController controller = loader.getController();
      controller.setMainApp(this);
    } catch (IOException e) {
      System.exit(0);
    }
  }

  // Returns the main stage.

  public Stage getPrimaryStage(){
    return primaryStage;
  }

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

我的app.view包中的控制器包含handleDeleteBtn按钮(以及其他几个按钮)和handleSelectedGridPaneRow()上的侦听器,以管理网格窗格中的行选择:

public class AppController {
    //Reference to MainApp
  private MainApp mainApp;

  @FXML
  private void handleRestoreBtn(){
    System.out.println("You are restoring the hidden row");
  }
  @FXML
  private void handleDeleteBtn(){
    System.out.println("You are hiding the selected row");
  }
  @FXML
  private void handleExitBtn(){
    System.exit(0);
  }
  @FXML
  private void handleSelectedGridPaneRow(){
    System.out.println("You have selected a row to hide");
  }

  public AppController(){}

 // Initialize the <code>AppController</code> instance. 
 @FXML
 private void initialize(){}

 public void setMainApp(MainApp mainApp)
 {
   this.mainApp = mainApp;
 }

}

我的具体问题是:
1)这种规格是否可以实现,即能够如上所述动态管理网格窗格? 2)如果是,我将在何处以及如何访问网格窗格?大概在AppController中'handleDeleteBtn()'方法的某个地方。我需要做什么来引用Controller中的gridpane,然后执行gridPane.getChildren().remove(0,2);等语句?

1 个答案:

答案 0 :(得分:0)

我认为事实上我知道我的帖子的答案表明我的方法都是错的。无论如何,我发现的解决方案非常有效。我没有尝试删除和恢复网格窗格中的行,而是将网格窗格单独留在原始的1列和3行中,而是根据按下的按钮更改每个单元格的内容。因此,我将按钮处理程序的名称更改为更能反映我正在尝试的内容,并添加了额外的内容以显示另一行的组合:

@FXML
private void showRow1and2Btn(){
...
}

@FXML
private void showRow2and3Btn(){
...
} 

@FXML
private void showAll(){
...
} 

然后我声明了三个标签来显示我想要的行的内容:

  @FXML
  private Label label_0;

  @FXML
  private Label label_1;

  @FXML
  private Label label_2;

这些标签绑定到我在Scene Builder中构建的三个标签,它们占据了网格窗格中的三行。

我添加了这个方法,以根据我的规范填充三个网格窗格行:

  private void setgridPaneRows(Label label, String str)
  {
    label.setText(str);
  }

然后只是在按钮处理程序中获取内容以便实现所需效果的情况,例如:

private void showRow1and2Btn()
{
  setgridPaneRows(label_0,"Label 0");
  setgridPaneRows(label_1,"Label 1");
  setgridPaneRows(label_2,null);
}

@FXML
private void showRow2and3Btn(){
  setgridPaneRows(label_0,"Label 1");
  setgridPaneRows(label_1,"Label 2");
  setgridPaneRows(label_2,null);
}

@FXML
private void ShowAllBtn(){
  setgridPaneRows(label_0,"Label 0");
  setgridPaneRows(label_1,"Label 1");
  setgridPaneRows(label_2,"Label 2");
}

在另一个应用程序中,我成功地扩展了这种方法,将第二列添加到gridpane并使用不同的控件填充这些元素,例如,我可以使gridpane 1,0包含一个输入需求的组合框,然后包含另一种输入要求的文本字段。