这可能更多的是设计选择,我想"为什么重新发明轮子"。有人可能已经要求这样做了。
(我不想去任何第三方框架,因为我的是一个小项目。我正在使用Adam Bein afterburner.fx
。我正在javafx中实现一个独立的应用程序。我对跟随MVC / MVP / MVVM非常感兴趣。由于javafx允许我使用fxml分离UI,因此我通过fxml完成了大部分UI设计。但是我遇到了一些问题。
TradeController
(我的所有UI事件处理(也是一些业务逻辑)都在这里)Trade
(实体类)现在我的TableView
中有一个JavaFX fxml
。所有TableColumn
都在fxml
本身中定义。我希望绑定到我的列的值是通过PropertyValueFactory
实现的,如果它是我的实体类中的直接属性。
TableView<Trade> myTableView;
例如:
<TableColumn fx:id="tradeOidTableColumn" prefWidth="130.0" text="Trade Oid">
<cellValueFactory><PropertyValueFactory property="oid"/></cellValueFactory>
</TableColumn>
但我希望在一列中显示商品短名称,其中Commodity
是与我的Trade
实体关系的另一个实体。所以我可以使用
myTradeEntity.commodity().commodityShortName();
获取值,完美无缺。但你们知道我不能这样做fxml
。它不支持嵌套绑定。
不可能
<cellValueFactory><PropertyValueFactory property="commodity.commodityShortName"/></cellValueFactory>
所以我被迫使用单元值工厂。我定义了一个类CommodityCellValueFactory
并绑定它。
例如:
<TableColumn fx:id="commodityTableColumn" prefWidth="220.0" text="Commodity">
<cellValueFactory><CommodityCellValueFactory /></cellValueFactory>
</TableColumn>
基本上我想摆脱细胞工厂和细胞价值工厂,除非我需要对我的价值进行一些格式化。所以我想我可以创建一个名为
的属性String tempCommodityShortName;
String getTempCommodityShortName()
{
return commodity.commodityShortName();
}
在我的Trade
实体中并将其绑定到我的表列。但我有15到20个属性。如果我在我的实体类中执行此操作,那么使用这些我不想做的额外帮助方法会使它变得臃肿。
我想为TradeEntityHelper
/ TradeEntityBusiness
/ TradeEntityAdditions
这样的每个实体都有一个帮助器类,我可以使用所有帮助器方法并在tableview列中访问它。
我的第一次尝试是代替类,我选择了一个接口(因为java 8接口支持默认方法)
interface ITradeEntityHelper
{
//all helper methods goes here
}
class TradeEntity implements ITradeEntityHelper
{
//real entity methods goes here
}
我会将界面绑定到我的TableView
。 TableView<ITradeEntityHelper>
代替TableView<TradeEntity>
如果我正在尝试愚蠢的事情,请纠正我
现在问题是如何在我的TradeEntity
界面中获取ITradeEntityHelper
引用,以便我可以询问
tradeEntity.Commodity().commodityShortName().
(或)喜欢这些
interface ITrade{}
class Trade implements ITrade{}
class TradeAdditions implements ITrade{}
将帮助器方法保留在Additions
类中。
我也想为我的Controller类实现相同的功能。
例如:
我的Application
中的每个Controller类都应该有基本接口,我希望在其中定义一些默认的java Predicate
和java 8 Function
,并希望在控制器类中重新生成。
class TradeController implements ITradeController, Initializable
{
}
答案 0 :(得分:0)
您可以使用{{3}}通过多级层次结构选择值。这允许您创建一个cellValueFactory
类:
import java.util.Arrays;
import javafx.beans.NamedArg;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.util.Callback;
public class NestedPropertyValueFactory<S, T> implements Callback<TableColumn.CellDataFeatures<S, T>, ObservableValue<T>> {
private final String[] steps;
private final PropertyValueFactory firstStepSelector;
/**
* @param property a string containing the names of the properties seperated
* by '.'.
*/
public NestedPropertyValueFactory(@NamedArg("property") String property) {
String[] properties = property.split("\\.");
firstStepSelector = new PropertyValueFactory<>(properties[0]);
this.steps = Arrays.copyOfRange(properties, 1, properties.length);
}
@Override
public ObservableValue<T> call(TableColumn.CellDataFeatures<S, T> param) {
// use PropertyValueFactory for first step and Bindings.select for
// additonal steps.
return Bindings.select(firstStepSelector.call(param), steps);
}
}
此类可用作fxml文件中的cellValueFactory
。
<cellValueFactory>
<NestedPropertyValueFactory property="commodity.commodityShortName"/>
</cellValueFactory>
请注意,如果任何中间步骤产生null
,您将在System.err
中收到警告。
同样使用此类,您需要使用符合命名约定的属性方法,即在这种情况下方法的名称应为commodityProperty
和commodityShortNameProperty
(或getCommodity
和{ {1}}它们是不可观察的。)