[英]Controller class for dynamic Javafx view
我是Javafx和Spring的 新手 ,並制作了一個簡單的桌面應用程序來從數據庫加載數據並將其顯示在tableview中 。 我將所有代碼放在一個類中,該類創建視圖並加載表並處理添加新行和表的編輯。 但是我很困惑如何將此類拆分為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批注獲取視圖對象。 但是在這種情況下,我正在類中創建視圖對象。 如果將此類分為視圖類和控制器類,那么如何定義動作讓我們說一下保存按鈕,以及如何訪問控制器類中的表視圖?
任何幫助將不勝感激。
如果將自定義JavaFx Node
創建為Bean
,則可以@Autowired
其自動綁定到控制器,但是必須向Node
添加一個代表自定義Node
。
您有兩種方法:
extends
類的Node
(或繼承人的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
}
}
鬃毛問題是必須在Controller
初始化之前將自定義Node
添加到上下文。 您可以編寫Configuration
來解決它:
@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());
}
}
ControlFx類:
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
-method編寫到自定義類中:
public void setOnActionSaveButton(EventHandler<ActionEvent> value){
save.setOnAction((ActionEvent e) -> {
// Some logic
}
}
我正在用代碼生成所有視圖,沒有任何fxml文件。 在那種情況下它將如何工作?
將@Controller
注釋( @Component
擴展)與@PostConstruct
注釋一起使用,或將@Autowired
與構造函數一起使用(或任何init
方式):
@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);
// }
}
在您的第二和第三代碼段中,您提到了加載fxml文件,但是我沒有任何文件。
您必須首先初始化spring-context。 我使用了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();
}
IMPL:
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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.