动态Javafx视图的控制器类

时间:2019-03-09 13:36:35

标签: java spring spring-boot javafx

我是 Javafx Spring 的新手,并制作了一个简单的桌面应用程序来从数据库中加载数据并在中显示表格视图。我将所有代码放在一个类中,该类创建表的视图加载并处理添加新行和编辑表的过程。但是我很困惑如何将此类分为 Controller View 部分(如MVC模式)。我的看起来像这样:

package com.waq;

// some imports

@Component
public class PartsView{

    private TableView table;
    TextField desc;
    Label title;
    Button save;
    GridPane grid;

    @Autowired
    private PartService partService;

    public PartsView(){
        createTable();
        grid = new GridPane();
        save = new Button();
        save.setText("Save");
        save.setOnAction((ActionEvent e) -> {
            // Some logic
        }
    }


    private void loadData() {
        List<Part> parts = partService.findAll();
        if(parts.size() > 0) {
            ObservableList<Part> observableArrayList = FXCollections.observableArrayList(parts);
            table.setItems( observableArrayList);
        }
        else
            table.setPlaceholder(new Label("No data to show."));
    }

    private void saveData(){
        // save record.
    }


    private void createTable(){
        CustomTableColumn<Part,String> idColumn = new CustomTableColumn<Part,String>("id");
        idColumn.setPercentWidth(10);
        idColumn.setCellValueFactory(new PropertyValueFactory<Part,String>("id"));

        CustomTableColumn<Part,String> descCol = new CustomTableColumn<Part,String>("description");
        descCol.setPercentWidth(50);
        descCol.setCellValueFactory(new PropertyValueFactory<Part,String>("description"));

        table.getColumns().addAll(idColumn,descCol);

        grid.getChildren().add(table);
    }

}

我看到了其他示例,但大多数示例都是在 fxml 文件中生成视图,然后使用 @FXML 批注获取视图对象。但是在这种情况下,我正在类中创建视图对象。如果将此类分为视图类和控制器类,那么如何定义动作让我们说一下保存按钮,以及如何访问控制器类中的表视图?

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

如果您将自定义JavaFx Node创建为Bean,则可以@Autowired将其添加到控制器,但是必须在Node中添加一个代表自定义{{ 1}}。

您有两种方法:

  1. Node您的extends类(或Node的继承人)(看例子)

  2. 从您的班级Node返回,该班级包含其他节点

示例:

root-Node

控制器应如下所示:

@Component
@Scope("prototype") //If you want to reuse component `@Scope("prototype")`
public class PartsView  extends GridPane{ 
  ...
  public void init(){
    getChildren().add(table);
  }

}

鬃毛问题是您必须在初始化public class TestController implements Initializable { @FXML //StackPane as example private StackPane stackPane; //injecting before constructor, when you load .fxml @Autowired private PartsView partsView; //injecting when you load spring-context @Override public void initialize(URL location, ResourceBundle resources) { // initialize fields marked @FXML annotation. // method initialize triggering after constructor } } 之前将自定义Node添加到上下文中。您可以编写Controller来解决它:

Configuration

ControlFx类:

@Configuration
@ComponentScan({
    "you.node.packege",
 })
public class TestConfig{

@Lazy                                  //depends on your case
@Bean
@Scope(BeanDefinition.SCOPE_PROTOTYPE) //depends on your case
public ControlFx<TabPane, PlanningController> testViewFx() throws IOException {
    return loadView("/view/TestLayout.fxml");
}


    private <V extends Node, C extends Initializable> ControlFx<V,C> loadView(String url) throws IOException {
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(getClass().getResource(url));
        return  new ViewFx<>(loader.load(), loader.getController());
    }
 }
  

我将此类分为视图类和控制器类,然后如何定义动作让我们说一下保存按钮,以及如何访问控制器类中的表视图?

您可以将public class ControlFx<N extends Node ,C extends Initializable> { private final N view; private final C controller; public ControlFx(N view, C controller) { this.view = view; this.controller = controller; } public N getView() { return view; } public C getController() { return controller; } } 方法写入自定义类:

facade
  

我正在使用代码生成所有视图,而没有任何fxml文件。在那种情况下它将如何工作?

public void setOnActionSaveButton(EventHandler<ActionEvent> value){ save.setOnAction((ActionEvent e) -> { // Some logic } } 注释(@Controller的扩展名)与@Component注释一起使用,或将@PostConstruct与构造函数一起使用(或任何@Autowired方式):

init
  

在您的第二和第三代码段中,您提到了加载fxml文件,但是我没有任何文件。

首先必须启动spring-context。我使用了@Controller public class TestController { private StackPane stackPane; // @Autowired private PartsView partsView; @Autowired public TestController (PartsView partsView){ ... stackPane.getChildren().add(partsView) } // @PostConstruct // private void beanPostConstruct() { // stackPane.getChildren().add(partsView); // } }

AnnotationConfigApplicationContext

插图:

public abstract class AbstractJavaFxApplication extends Application {

    private static String[] savedArgs;
    protected AnnotationConfigApplicationContext context;

    @Override
    public void init() {
        context =  new AnnotationConfigApplicationContext(configurations());
        context.getAutowireCapableBeanFactory().autowireBean(this);

    }

    @Override
    public void stop() throws Exception {
        super.stop();
        context.close();
    }

    protected static void launchApp(Class<? extends AbstractJavaFxApplication> clazz, String[] args) {
        AbstractJavaFxApplication.savedArgs = args;
        Application.launch(clazz, savedArgs);
    }

    protected abstract Class<?>[] configurations();
}

配置:

public class ReportApp extends AbstractJavaFxApplication {

    public final double PRIMARY_WINDOW_HEIGHT = 500;
    public final double PRIMARY_WINDOW_WIDTH = 500;

    @Value("${ui.title:JavaFX приложение}")
    private String windowTitle;

    @Autowired
    private RootLayoutController controller;

    @Override
    public void start(Stage stage) throws Exception {
        stage.setTitle(windowTitle);
        stage.setScene(
                new Scene(
                        controller.getPane(),
                        PRIMARY_WINDOW_WIDTH,
                        PRIMARY_WINDOW_HEIGHT
                )
        );
        stage.setResizable(true);
        stage.centerOnScreen();
        stage.show();
    }

    public static void main(String[] args) {
        launchApp(ReportApp.class, args);
    }

    @Override
    protected Class<?>[] configurations() {
        return new Class<?>[]{
            Config.class
        };
    }
}

控制器:

@Configuration
@ComponentScan({"components", "controllers"})
public class Config {

    @Bean
    ...
}