gpt4 book ai didi

java - 两个 JavaFx Controller 之间的通信

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:04:54 24 4
gpt4 key购买 nike

我制作了一个 Controller 和 View 结构 (fxml) 以尽可能多地分离我的代码,我想知道如何在 2 个 Controller 之间进行通信。我的意思是,一个 Controller 必须调用另一个 Controller 的某些功能才能将其设置为最新。

我认为我当前结构的模式会更明确:

Controller 1
/\
fx:include fx:include
/\
Controller 2 Controller 3

每个 Controller 都有自己的 fxml View 。
- Controller 1:一个容器 Controller ,它有一个带有 2 个选项卡的 TabPane 元素(每个选项卡对应 1 个 Controller )
- Controller 2:列表
- Controller 3:一个表格

您可能已经猜到我希望我的表单( Controller 3)自动更新我的列表( Controller 2)。目前,表单只是一个“创建表单”,所以我只想在我的列表中添加行。

我已经尝试使用 FXMLLoader 获取我的 Controller 2 并调用函数来重新加载我的 tableView,但没有成功。

Controller 1(.java + .fxml):

package pappu.controllers;

import pappu.core.controller.AbstractController;

public class FolderController extends AbstractController
{

}


<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<VBox fx:id="view" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="pappu.controllers.FolderController">
<TabPane>
<tabs>
<Tab text="RECHERCHE">
<content>
<AnchorPane id="Content">
<children>
<fx:include source="FolderList.fxml" />
</children>
</AnchorPane>
</content>
</Tab>
<Tab text="DOSSIER">
<content>
<AnchorPane id="Content">
<children>
<fx:include source="FolderFormAdd.fxml" />
</children>
</AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>
</VBox>

Controller 2(.java + .fxml):

package pappu.controllers;

import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.ResourceBundle;

import org.hibernate.Session;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.util.Callback;
import pappu.core.controller.AbstractController;
import pappu.entities.Folder;

public class FolderListController extends AbstractController implements Initializable
{
/**
* TableView object
*/
@FXML private TableView<Folder> foldersTableView;

/**
* FolderNumber column object
*/
@FXML private TableColumn<Folder, String> colFolderNumber;

/**
* Person column object
*/
@FXML private TableColumn<Folder, String> colPerson;

/**
* Birthday date column object
*/
@FXML private TableColumn<Folder, Date> colBirthdayDate;

/**
* List of folders
*/
private static List<Folder> foldersList;

/**
* Constructor
* Will make a call to initializeFoldersList()
*/
public FolderListController()
{
initializeFoldersList();
}


/**
* Initialize implementation of the Initializable interface
*
* @param location
* @param resources
*/
@Override
public void initialize(URL location, ResourceBundle resources)
{
initializeTableColumns();
loadData();
}

/**
* Query the database to retrieve the folder list
*/
@SuppressWarnings("unchecked")
public void initializeFoldersList()
{
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
foldersList = session.createQuery("from Folder").list();
session.close();
}

/**
* Initialize columns binding to folders properties
*/
public void initializeTableColumns()
{
colFolderNumber.setCellValueFactory(
new PropertyValueFactory<Folder,String>("folderNumber")
);
colPerson.setCellValueFactory(
new Callback<CellDataFeatures<Folder, String>, ObservableValue<String>>() {
public ObservableValue<String> call(CellDataFeatures<Folder, String> p) {
return new SimpleStringProperty(p.getValue().getFirstName() + " " + p.getValue().getLastName());
}}
);
colBirthdayDate.setCellValueFactory(
new PropertyValueFactory<Folder,Date>("birthdayDate")
);

}

/**
* Put the folders list in the TableView object
*/
public void loadData()
{
ObservableList<Folder> listFold = FXCollections.observableArrayList(foldersList);
foldersTableView.setItems(listFold);
}
}


<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.Label?>


<VBox fx:id="view" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="pappu.controllers.FolderListController">
<Label fx:id="lblTest"></Label>
<TableView fx:id="foldersTableView">
<columns>
<TableColumn prefWidth="75.0" text="N°" fx:id="colFolderNumber">
</TableColumn>
<TableColumn prefWidth="75.0" text="Personne" fx:id="colPerson">
</TableColumn>
<TableColumn prefWidth="75.0" text="Date de naissance" fx:id="colBirthdayDate">
</TableColumn>
</columns>
</TableView>
</VBox>

Controller 3(.java + .fxml):

package pappu.controllers;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

import org.hibernate.Session;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;
import pappu.core.AppFactory;
import pappu.core.controller.AbstractController;
import pappu.entities.Folder;
import pappu.entities.Gender;

public class FolderFormAddController extends AbstractController
{
@FXML TextField folderNumber;
@FXML TextField firstName;
@FXML TextField lastName;
public void submitForm() throws IOException
{
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();

Folder folder = new Folder();

folder.setFolderNumber(folderNumber.getText());
folder.setFirstName(firstName.getText());
folder.setLastName(lastName.getText());
folder.setGender(Gender.m);

session.save(folder);
session.getTransaction().commit();
// This doesn't work.. even tried with a simple Label
AppFactory app = new AppFactory();
FolderListController flc = app.folderListController();
flc.initializeFoldersList();
flc.loadData();
}
}


<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<VBox fx:id="view" prefHeight="216.0" prefWidth="421.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="pappu.controllers.FolderFormAddController">
<children>
<Label prefHeight="26.0" prefWidth="102.0" text="Numéro de dossier" />
<TextField prefWidth="200.0" fx:id="folderNumber"/>
<Label text="Prénom" />
<TextField prefWidth="200.0" fx:id="firstName"/>
<Label text="Nom" />
<TextField prefWidth="200.0" fx:id="lastName"/>
<Button mnemonicParsing="false" onAction="#submitForm" text="Enregistrer" />
</children>
</VBox>

精度:
我在这个基础上提出了我的申请: http://www.zenjava.com/2011/10/25/views-within-views-controllers-within-controllers/我在 Java JDK 7 上使用 JavaFX 2

我觉得 JavaFX 应用程序的全局功能中缺少一些东西。

最佳答案

Nikos 在耦合方面提出了一个很好的观点(软件工程原则)。但是,有一种方法可以实现第一种(简单)方法的“精神”,而不是通过使用中介者模式来侵犯这一原则。摘自维基百科(引用 GoF):

"The essence of the Mediator Pattern is to "define an object that encapsulates how a set of objects interact". It promotes loose coupling by keeping objects from referring to each other explicitly, and it allows their interaction to be varied independently. Client classes can use the mediator to send messages to other clients, and can receive messages from other clients via an event on the mediator class."

在这里您可以将您的 Controller 视为客户端。然后您需要做的是使用调解器调解彼此之间的“对话”。

首先创建一个调解器接口(interface):

public interface IMediateControllers {
void registerController2(Controller2 controller);
void registerController3(Controller3 controller);
void controller2DoSomething();
void controller3OperateOn(String data);
}

然后是一个具体的中介(作为一个单例)

public class ControllerMediator implements IMediateControllers {
private Controller2 controller2;
private Controller3 controller3;

@Override
void registerController2(Controller2 controller) {
controller2 = controller;
}

@Override
void registerController3(Controller3 controller) {
controller3 = controller;
}

@Override
void controller2DoSomething() {
controller2.doSomething();
}

void controller3OperateOn(String data) {
controller3.operateOn(data);
}

/**
* Everything below here is in support of Singleton pattern
*/
private ControllerMediator() {}

public static ControllerMediator getInstance() {
return ControllerMediatorHolder.INSTANCE;
}

private static class ControllerMediatorHolder {
private static final ControllerMediator INSTANCE = new ControllerMediator();
}
}

现在,由于 Controller1 已注入(inject) Controller2 和 Controller3(如 fxml 文件中所述),您可以在 Controller1::initialize() 方法中执行以下操作:

@Override
public void initialize(Url url, ResourceBundle resource) {
ControllerMediator.getInstance().registerController2(controller2Controller);
ControllerMediator.getInstance().registerController3(controller3Controller);
}

现在,在任何需要 Controller2 与 Controller3 通信的地方,您只需使用调解器即可:

// ... somewhere in Controller2
ControllerMediator.getInstance().controller3OperateOn("my data");

并且 Controller 3 可以使用相同的中介与 Controller2 通信:

// ... somewhere in Controller3
ControllerMediator.getInstance().controller2DoSomething();

当然,这依赖于Controller2实现了doSomething()操作,Controller3实现了operateOn(String data)操作。

重要的是您已经解耦了 Controller2 和 Controller3(它们彼此不了解)。我刚刚在我现在正在进行的一个小项目中使用了这种模式(受到 Nikos 的第一个解决方案的启发,但立即想到了调解器模式来消除他(正确地)提示的耦合。

关于java - 两个 JavaFx Controller 之间的通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22178533/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com