用于动态Javafx视图的控制器类
我不熟悉Javafx和Spring,并制作了一个简单的桌面应用程序,从数据库中加载数据,并将其显示在表视图中。我将所有代码放在一个类中,该类创建视图和加载表,并处理添加新行和编辑表。但是我不知道如何将这个类划分为控制器和视图部分(类似MVC模式)。我的类如下所示:用于动态Javafx视图的控制器类,java,spring,spring-boot,javafx,Java,Spring,Spring Boot,Javafx,我不熟悉Javafx和Spring,并制作了一个简单的桌面应用程序,从数据库中加载数据,并将其显示在表视图中。我将所有代码放在一个类中,该类创建视图和加载表,并处理添加新行和编辑表。但是我不知道如何将这个类划分为控制器和视图部分(类似MVC模式)。我的类如下所示: package com.waq; // some imports @Component public class PartsView{ private TableView table; TextField des
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);
}
}
package com.waq;
//一些进口商品
@组成部分
公共类PartsView{
私有表视图表;
TextField desc;
标签名称;
按钮保存;
网格窗格网格;
@自动连线
私人部分服务;
公共部分视图(){
createTable();
grid=新的GridPane();
保存=新建按钮();
save.setText(“save”);
save.setOnAction((ActionEvent e)->{
//一些逻辑
}
}
私有void loadData(){
List parts=partService.findAll();
如果(parts.size()>0){
ObservableList observableArrayList=FXCollections.observableArrayList(部件);
表.集合项目(可观察的列表);
}
其他的
table.setPlaceholder(新标签(“无数据显示”);
}
私有void saveData(){
//保存记录。
}
私有void createTable(){
CustomTableColumn idColumn=新的CustomTableColumn(“id”);
idColumn.setPercentWidth(10);
idColumn.setCellValueFactory(新属性ValueFactory(“id”);
CustomTableColumn descCol=新的CustomTableColumn(“说明”);
描述设置百分比宽度(50);
描述setCellValueFactory(新属性ValueFactory(“说明”);
table.getColumns().addAll(idColumn,descCol);
grid.getChildren().add(表);
}
}
我看到了其他示例,但大多数示例都是在fxml文件中生成视图,然后使用@fxml注释获取视图对象。但在我的示例中,我在类中创建视图对象。如果我在视图类和控制器类中分离该类,那么我将如何定义该操作,例如save按钮和如何在controller类中访问表视图
任何帮助都将不胜感激。如果您将自定义JavaFx
节点
创建为Bean
,您可以@Autowired
将其添加到控制器,但您必须将一个添加到节点
,它代表您的自定义节点
你有两种方法:
扩展了节点
的类(或节点
的继承人)(查看示例)
根节点返回
@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
}
}
问题在于,在初始化控制器
之前,您必须将自定义节点
添加到上下文中。您可以编写配置
来解决此问题:
@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());
}
}
我用代码生成所有视图,没有任何fxml文件。在这种情况下,它将如何工作 使用
@Controller
注释(扩展@Component
)和@PostConstruct
注释,或使用@Autowired
和构造函数(或任何init
方式):
在第2和第3段代码中,您提到加载fxml文件,但我没有 首先必须初始化spring上下文。我使用了
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();
}
控制器:
@Controller
public class RootLayoutController {
private StackPane stackPane;
@Autowired
private PartsView partsView;
@PostConstruct
private void init(){
stackPane = new StackPane();
stackPane.getChildren().add(partsView);
}
public Pane getPane(){
return stackPane;
}
}
我用代码生成所有视图,没有任何fxml文件。在这种情况下,它将如何工作?在您的第2和第3个代码段中,您提到加载fxml文件,但我没有任何文件。@Waqar Ahmed请看示例
@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);
// }
}
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
...
}
@Controller
public class RootLayoutController {
private StackPane stackPane;
@Autowired
private PartsView partsView;
@PostConstruct
private void init(){
stackPane = new StackPane();
stackPane.getChildren().add(partsView);
}
public Pane getPane(){
return stackPane;
}
}