关于如何显示JavaFX ListView单元格的从属视图的建议
我们希望将ListView填充为单个JavaFX视图的实例列表。这是我们试图早点开始工作的事情,但时间不够了。当时的后备解决方案是有一个四行的静态面板(即不使用ListView)。在静态版本中,每一行都是同一JavaFX(FXML)视图的实例 每一行都是与一个小FXML文件匹配的控制器的一个单独(实例)。其工作方式是,当调用initialize()方法时,视图将获得一个id,该id映射到模型数据,然后控制器/“视图”管理自己的数据行。在静态情况下,我们可以使用FXML include指令,这使事情变得非常简单。我将调用单独的行,一个行视图 要以这种方式使用ListView,我们需要执行以下操作:关于如何显示JavaFX ListView单元格的从属视图的建议,java,listview,javafx-8,Java,Listview,Javafx 8,我们希望将ListView填充为单个JavaFX视图的实例列表。这是我们试图早点开始工作的事情,但时间不够了。当时的后备解决方案是有一个四行的静态面板(即不使用ListView)。在静态版本中,每一行都是同一JavaFX(FXML)视图的实例 每一行都是与一个小FXML文件匹配的控制器的一个单独(实例)。其工作方式是,当调用initialize()方法时,视图将获得一个id,该id映射到模型数据,然后控制器/“视图”管理自己的数据行。在静态情况下,我们可以使用FXML include指令,这使事
- 如果ListView可以采用(子)视图/(子)组件,那么这样做似乎没有问题
- 行视图是预打包的子视图李>
- 是否有方法“克隆”现有视图以制作副本
public class CustomListView
{
:
public class CustomCellFactory implements Callback<ListView<MyObject>, ListCell<MyObject>>
{
@Override
public ListCell<MyObject> call( ListView<MyObject> listView ) {
ListCell<MyObject> cell = new ListCellType();
return cell;
}
}//CustomCellCallback class
}//CustomListView
公共类CustomListView
{
:
公共类CustomCellFactory实现回调
{
@凌驾
公共ListCell调用(ListView ListView){
ListCell=新的ListCellType();
返回单元;
}
}//CustomCellCallback类
}//自定义列表视图
在我看来,工厂模式的逻辑,然后新ListCellType()应该返回加载的AnchorPane作为视图。其中ListCellType定义为
公共类ListCellType扩展ListCell
{
:
}//列表单元类型
然而,在我看来,似乎我们需要工厂返回加载的视图,因此
ListCell<MyObject> cell = new ListCellType();
ListCell cell=new ListCellType();
这个应用程序需要返回一个JavaFX,或者在这个特定的情况下返回一个(稍后我们可以使它更通用)。好像:
ListCell,需要ListView而不是节点
如何做到这一点,也许使用不同的工厂/更新方案?我相信我们已经找到了一个原始答案,它足以证明概念,并可用作“通用”模式的起点。内核来自此自定义ListView示例的几个扩展:
- ,及
如前所述。这些示例使用简单对象作为列表内容。第一个要求是拥有子视图的列表视图,其中子视图是另一个FXML文件。从概念上讲,这类似于使用FXML运算符的ListVew
原始解决方案的基础是将单元数据与单元视图配对。因此,对于自定义单元格视图列表,ListView需要一个(视图、数据)元组的可观察列表。或者,当子视图的控制器足够智能,可以在模型中查找数据时,这可能只是一个“子视图列表”。现在,我们的原始示例将数据和视图的一个实例放在一起,即
public class ListCellView extends CellView
{
@FXML private Label label1;
@FXML private Label label2;
@Override
public void setInfo( MyObject myObject ){
label1.setText( myObject.getDay() );
label2.setText( Integer.toString( myObject.getNumber() ) );
label1.setTextFill( myObject.getColor() );
}
/**
* Initialize
* -- must use java -ea <program>, to check asserts
**/
@FXML
@Override
protected void initialize() {
super.initialize();
assert label1 != null : "fx:id=\"label1\" was not injected: check your FXML file 'CustomCell.fxml'.";
assert label2 != null : "fx:id=\"label2\" was not injected: check your FXML file 'CustomCell.fxml'.";
}
}//ListCellView
在运行时代码中,ListView类:CustomListView由JavaFX应用程序平台加载。为了测试该过程,我们使用静态数据初始化了显示,所有这些数据都使用相同的FXML视图,如下所示的“MyObject”对象列表
public class CustomListView
{
@FXML private ResourceBundle resources;
@FXML private URL location;
@FXML private ListView<MyObject> listView;
List<MyObject> myList = prepareMyList();
ObservableList<MyObject> myObservableList = FXCollections.observableList( this.myList );
private void setListView(){
this.listView.setItems( this.myObservableList );
listView.setCellFactory(
new Callback<ListView<MyObject>, javafx.scene.control.ListCell<MyObject>>() {
@Override
public ListCell<MyObject> call(ListView<MyObject> listView) {
return new CustomListCell();
}
}//callback
);//setCellFactory
}//setListView
/**
* Initializes the controller class.
*/
@FXML
void initialize() {
assert listView != null : "fx:id=\"listView\" was not injected: check your FXML file 'CustomList.fxml'.";
this.setListView();
}
/**
* Prepare My List
* - Create dummy list of Views and data = MyObject-s
**/
private List<MyObject> prepareMyList() {
final String FXML_VIEW = "/fxml/ListCell.fxml";
List<MyObject> newList = new ArrayList<>();
newList.add(new MyObject( FXML_VIEW, "Sunday", 50, Color.RED ));
newList.add(new MyObject( FXML_VIEW, "Monday", 60, Color.GREEN ));
newList.add(new MyObject( FXML_VIEW, "Tuesday", 20, Color.BLUE ));
newList.add(new MyObject( FXML_VIEW, "Wednesday", 90, Color.VIOLET ));
newList.add(new MyObject( FXML_VIEW, "Thursday", 30, Color.BLUEVIOLET ));
newList.add(new MyObject( FXML_VIEW, "Friday", 62, Color.BROWN ));
newList.add(new MyObject( FXML_VIEW, "Saturday", 65, Color.GOLD ));
return newList;
}
}//CustomListView
MyObject保留“ViewLoader”类型,以在加载后保存FXML视图和控制器
public class ViewLoader
{
private String fxmlStr = "(none)";
private Parent rootNode = null;
private CellView viewController = null;
public void loadView( final String urlStr ){
Parent root = null;
URL fxmlResource;
FXMLLoader fxmlLoader = null;
try
{
fxmlResource = getClass().getResource( urlStr );
fxmlLoader = new FXMLLoader( fxmlResource, Resources.getResourceBundle() );
root = fxmlLoader.load( );
this.viewController = fxmlLoader.getController();
this.fxmlStr = urlStr;
this.rootNode = root;
}
catch (Exception ex)
{
puts( " * Exception on FXMLLoader.load()");
puts( " * "+ex.getMessage());
puts( " ----------------------------------------\n");
}
}
public CellView getView(){
return this.viewController;
}
public ViewLoader( final String urlStr ){
loadView( urlStr );
}
}//ViewLoader class
此示例在JavaFX ListView中愉快地显示了下级视图单元格的列表。子视图需要理解“MyObject”数据。在最终版本中,数据将与子视图解耦,并从某个模型对象检索
每个ListView单元格都是正在使用的特定“ListCellView”控制器的唯一实例。对此模式的改进将能够使用数据源初始化子视图,并保持数据与视图的干净分离。与此不同,子视图必须手动加载。如果需要,可以在CustomListView.FXML主目录中将FXML文件名指定为不可见标签
希望其他人觉得它有用,或者如果没有,至少你可以看到更多管理ListView-s的工作方式。hmm。。。从技术上讲,您需要知道要加载哪个fxml的数据元素列表和从该fxml加载视图的cellFactory。但从未尝试过。只想对每一行重复使用相同的FXML。那么你说的是一个定制的细胞工厂。
public class ListCellView extends CellView
{
@FXML private Label label1;
@FXML private Label label2;
@Override
public void setInfo( MyObject myObject ){
label1.setText( myObject.getDay() );
label2.setText( Integer.toString( myObject.getNumber() ) );
label1.setTextFill( myObject.getColor() );
}
/**
* Initialize
* -- must use java -ea <program>, to check asserts
**/
@FXML
@Override
protected void initialize() {
super.initialize();
assert label1 != null : "fx:id=\"label1\" was not injected: check your FXML file 'CustomCell.fxml'.";
assert label2 != null : "fx:id=\"label2\" was not injected: check your FXML file 'CustomCell.fxml'.";
}
}//ListCellView
public abstract class CellView
{
@FXML private ResourceBundle resources;
@FXML private URL location;
@FXML private AnchorPane customCell;
@FXML private HBox hBox;
public abstract void setInfo( MyObject myObject );
public HBox getBox() {
return hBox;
}
protected void initialize() {
assert customCell != null : "fx:id=\"customCell\" was not injected: check your FXML file 'CustomCell.fxml'.";
assert hBox != null : "fx:id=\"hBox\" was not injected: check your FXML file 'CustomCell.fxml'.";
}
public CellView(){
}
}//CellView
public class CustomListView
{
@FXML private ResourceBundle resources;
@FXML private URL location;
@FXML private ListView<MyObject> listView;
List<MyObject> myList = prepareMyList();
ObservableList<MyObject> myObservableList = FXCollections.observableList( this.myList );
private void setListView(){
this.listView.setItems( this.myObservableList );
listView.setCellFactory(
new Callback<ListView<MyObject>, javafx.scene.control.ListCell<MyObject>>() {
@Override
public ListCell<MyObject> call(ListView<MyObject> listView) {
return new CustomListCell();
}
}//callback
);//setCellFactory
}//setListView
/**
* Initializes the controller class.
*/
@FXML
void initialize() {
assert listView != null : "fx:id=\"listView\" was not injected: check your FXML file 'CustomList.fxml'.";
this.setListView();
}
/**
* Prepare My List
* - Create dummy list of Views and data = MyObject-s
**/
private List<MyObject> prepareMyList() {
final String FXML_VIEW = "/fxml/ListCell.fxml";
List<MyObject> newList = new ArrayList<>();
newList.add(new MyObject( FXML_VIEW, "Sunday", 50, Color.RED ));
newList.add(new MyObject( FXML_VIEW, "Monday", 60, Color.GREEN ));
newList.add(new MyObject( FXML_VIEW, "Tuesday", 20, Color.BLUE ));
newList.add(new MyObject( FXML_VIEW, "Wednesday", 90, Color.VIOLET ));
newList.add(new MyObject( FXML_VIEW, "Thursday", 30, Color.BLUEVIOLET ));
newList.add(new MyObject( FXML_VIEW, "Friday", 62, Color.BROWN ));
newList.add(new MyObject( FXML_VIEW, "Saturday", 65, Color.GOLD ));
return newList;
}
}//CustomListView
public class MyObject
{
private ViewLoader view = null;
private String day;
private int number;
private Color colour;
public String getDay() {
return day;
}
public int getNumber() {
return number;
}
public Color getColor(){
return colour;
}
public CellView getView(){
return this.view.getView();
}
public MyObject( final String fxmlView, final String d, final int n, final Color c) {
view = new ViewLoader( fxmlView );
day = d;
number = n;
colour = c;
}
}//MyObject class
public class ViewLoader
{
private String fxmlStr = "(none)";
private Parent rootNode = null;
private CellView viewController = null;
public void loadView( final String urlStr ){
Parent root = null;
URL fxmlResource;
FXMLLoader fxmlLoader = null;
try
{
fxmlResource = getClass().getResource( urlStr );
fxmlLoader = new FXMLLoader( fxmlResource, Resources.getResourceBundle() );
root = fxmlLoader.load( );
this.viewController = fxmlLoader.getController();
this.fxmlStr = urlStr;
this.rootNode = root;
}
catch (Exception ex)
{
puts( " * Exception on FXMLLoader.load()");
puts( " * "+ex.getMessage());
puts( " ----------------------------------------\n");
}
}
public CellView getView(){
return this.viewController;
}
public ViewLoader( final String urlStr ){
loadView( urlStr );
}
}//ViewLoader class