请说明如何使用CheckBoxTableCell [英] Please Explain How to Use CheckBoxTableCell

查看:146
本文介绍了请说明如何使用CheckBoxTableCell的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想了解更多有关如何实际使用或子类化CheckBoxTableCell的信息(如有必要).在这种情况下,我想使用此类,因此该复选框不会绑定到基础数据模型属性.

I would like to know more about how to practically use or subclass (if necessary) CheckBoxTableCell. There is one specific case I would like to use this class, whereby the check box doesn't bind to the underlying data model property.

假设我有一个名为选择"的列,其中包含复选框.此列或多或少充当该行的可视标记.用户可以在这些框上打勾,然后使用按钮对被打勾的行执行一些操作(例如,删除所有被打勾的行).

Suppose that I have a column call 'Select' that has check boxes in them. This column, more or less serve as a visual marker against the row. An user could tick these boxes and then use a button to execute some action against the ticked rows (e.g. delete all ticked rows).

我正在搜索有关此主题的教程.尽管有一些教程或解释,但其中涉及与复选框相关的一些后备数据模型.

I've search for tutorials on this subject. Whilst there were some tutorials or explanations on it, however, they involved some backing data model relating to the checkbox.

因此,我正在寻找更详细的解释,该复选框是动态生成的,并且可以作为用户界面的辅助工具,例如上面说明的示例.此外,我想知道编辑是如何起作用的,并按照标准和约定正确地对其进行编码,尤其是当Java 8引入了具有属性,新的javafx类等的更新时.

So I'm looking for a more detail explanation on this, where the checkbox is dynamically generated and serve as an auxilliary aid to the user interface such as the example that was explained above. Furthermore, I would like to know how does editing comes into play and coding it correctly to standards and conventions, particularly when Java 8 introduced updates with property, new javafx classes, etc.

如果有帮助,一个常见的参考示例可以是人"的数据模型,该模型仅具有一个属性名称".一个ObservableList可以绑定到一个显示名称的TableView上.设置在(表视图)最左侧的另一列是每个名称对应的复选框.最后,至少一个按钮允许某种形式的人员列表操纵.为了简单起见,该按钮只是根据在操作该按钮时是否在该人的姓名上打了勾号,才从列表中删除该人.此外,可以创建一个按钮来添加新的人,但是它可以是可选的.

If it assists, a common reference example could be a data model of 'Person', which only has one property 'Name'. A ObservableList could be bounded to a TableView which displays the names. And the other column set to the leftmost side (of the tableview) are check boxes against each name. Lastly, at least one button allow some form of manipulation of the list of person. And to make it simple, that button simply removes person(s) in the list based on whether a tick was marked against the person's name when the button is actioned. Furthermore, a button could made to add new person, but it could be optional.

我希望我已经以简洁明了的方式撰写了主题,并且对此有一个明确的解决方案.预先感谢任何可以提供任何相关信息的人.

I hope I've written topic in a concise and detailed manner and that there is a definitive solution to it. Thank you in advance to anyone that can provide any relevant information.

推荐答案

使用如上所述的数据模型Person示例,是一个布尔属性,例如已添加注册状态,因此将第三个表名为已注册"的表列添加到TableView.

Using the data model Person example described as above, a boolean property, e.g. Registered status, is added and so a third table column called 'Registered' is added to the TableView.

考虑代码示例:

//The Data Model
public class Person
{
    /*
     * Fields
     */
    private StringProperty firstName;

    private StringProperty lastName;

    private BooleanProperty registered;


    /* 
     * Constructors
     */
    public Person(String firstName, String lastName, boolean registered)
    {
        this.firstName = new SimpleStringProperty(firstName);
        this.lastName = new SimpleStringProperty(lastName);
        this.registered = new SimpleBooleanProperty(registered);
    }

    public Person()
    {
        this(null, null, false);
    }

    /*
     * Properties
     */

    public StringProperty firstNameProperty() { return firstName; }

    public String getFirstName() { return this.firstName.get(); }

    public void setFirstName(String value) { this.firstName.set(value); }


    public StringProperty lastNameProperty() { return lastName; }

    public String getLastName() { return this.lastName.get(); }

    public void setLastName(String value) { this.lastName.set(value); }


    public BooleanProperty registeredProperty() { return registered; }

    public boolean isRegistered() { return this.registered.get(); }

    public void setRegistered(boolean value) { this.registered.set(value); }
}


//Dummy values for the data model
List<Person> personList = new ArrayList<Person>();
personList.add( new Person("John", "Smith", true) ;
personList.add( new Person("Jack", "Smith", false) );


TableView<Person> tblView = new TableView<Person>();

tblView.setItems( FXCollections.observableList(personList) );

TableColumn firstName_col = new TableColumn("First Name");
TableColumn lastName_col = new TableColumn("Last Name");
TableColumn registered_col = new TableColumn("Registered");

firstName.setCellValueFactory(new PropertyValueFactory<Person,String>("firstName"));
lastName.setCellValueFactory(new PropertyValueFactory<Person,String>("lastName"));

registered_col.setCellValueFactory(
new Callback<CellDataFeatures<Person,Boolean>,ObservableValue<Boolean>>()
{
    //This callback tell the cell how to bind the data model 'Registered' property to
    //the cell, itself.
    @Override
    public ObservableValue<Boolean> call(CellDataFeatures<Person, Boolean> param)
    {   
        return param.getValue().registeredProperty();
    }   
});

//This tell how to insert and render a checkbox in the cell.
//
//The CheckBoxTableCell has the updateItem() method which by default links up the
//cell value (i.e. the 'Registered' property to the checkbox.  And this method is
//automatically call at the appropriate time, such as when creating and rendering
//the cell (I believe).
//
//In this case, as the registed_col.setCellValueFactory() method has specified
//'Registered' in the actual data model (i.e. personList), therefore the checkbox will
//be bound to this property.
registered_col.setCellFactory( CheckBoxTableCell.forTableColumn(registered_col) );

tblView.getColumns.addAll(firstName_col, lastName_col, registered_col);

//table display preference - should not affect this exercise/problem
tblView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);


此代码正常工作.通过数据模型或tblView UI组件进行迭代以访问Registered属性时,即使更改(例如取消/选中复选框),它也会显示正确的值.

This code works correctly. When iterating either through the data model or tblView UI component to access the Registered property, it will show the correct values, and even when it changes (i.e. un/ticking the checkbox).

尝试添加未绑定到数据模型的复选框的原始问题尚未得到解决.

The original problem of trying to add a checkbox that does not bind to the data model is yet to be answered.

假设添加了另一个列调用选择",它仅包含一个复选框以直观地指示可以(或选择)一个或多个行.重申一下,此复选框列与数据模型Person没有任何相关含义.因此,在Person类内部创建一个属性来保存该值在语义上是不必要的,并且可能被认为是不良的编码实践.那么这个问题怎么解决呢?

Suppose another column call 'Select' is added and it simply contains a checkbox to visually indicate that one or more rows can be (or is) selected. Reiterating, this column of checkboxes does not have any relevant meaning to the data model Person. And thus creating a property inside the Person class to hold this value is semantically unnecessary and probably considered poor coding practice. So how this problem solved?

如何将任意BooleanProperty(或针对personList中每个人的列表)链接或绑定到相应的复选框?

How is the linking or binding an arbitrary BooleanProperty (or a list of it for each person in the personList) to the corresponding checkbox?

TableColumn select_col = new TableColumn("Select");

//Set a boolean property to represent cell value.
select_col.setCellValueFactory(
new Callback<CellDataFeatures<Person,Boolean>,ObservableValue<Boolean>>()
{
    @Override
    public ObservableValue<Boolean> call(CellDataFeatures<Person,Boolean> param)
    {
        //PROBLEM -- What Code goes here?
    }
};

//This call should be okay - it would display the checkbox according to the provided
//boolean (property).  This was proven with 
//registered_col.setCellFactory(CheckBoxTableCell.forTableColumn(registered_col)
select_col.setCellFactory(CheckBoxTableCell.forTableColumn(select_col);


一种解决方案是创建一个子类的(匿名)内部类,并添加'Select'属性.使用与已注册"属性及其表列类似的代码来链接选择"属性,它应该可以工作.如上所述,仅用于解决视觉问题的子类会破坏数据模型的语义.

One solution is to create an (anonymous) inner class that subclass Person and add the 'Select' property. Using similar code to the 'Registered' property and its table column to link the 'Select' property, it should work. As stated above, subclassing just to solve a visual problem breaks the data model semantic.

更好的解决方案可能是-为personList中的每个人创建一个内部布尔属性列表,并将它们链接在一起.那么,如何在setCellValueFactory()方法中检索与personList中每个人相对应的适当的布尔属性?一种可能的解决方案是使用personList中的索引位置,select列的布尔属性列表和行索引.因此,归结为将行索引放入setCellValueFactory(CellDataFeatures)内,这如何正确完成?

A better solution could be - to create an internal list of boolean property for each person in personList and linking them together. So how is the appropriate boolean property being retrieve that correspond to each person in personList in the setCellValueFactory() method? One possible solution to this is to use the index position in the personList, the list of boolean property for the select column, and the row index. So it comes down to getting the row index inside the setCellValueFactory(CellDataFeatures), and how is this done correctly?

考虑代码:

TableColumn<Person,Boolean> select_col = new TableColumn<Person,Boolea>("Select");

List<BooleanProperty> selectedRowList = new ArrayList<BooleanProperty>();

//This callback allows the checkbox in the column to access selectedRowList (or more
//exactly, the boolean property it contains
Callback<Integer,ObservableValue<Boolean>> selectedStateSelectColumn =
    new Callback<Integer,ObservableValue<Boolean>>()
{

    //index in this context reference the table cell index (I believe)
    @Override
    public ObservableValue<Boolean> call(Integer index)
    {
        return selectedRowList.get(index);
    }
}

//Initialise the selectedRowList
for(Person p : personList)
{
    //initially, it starts off as false, i.e. unticked state
    selectedRowList.add( new SimpleBooleanProperty() ); 
}

select_col.setCellValueFactory(
    new Callback<CellDataFeatures<Person,Boolean>,ObservableValue<Boolean>>
{
    //retrieve the cell index and use it get boolean property in the selectedRowList
    @Override
    public ObservableValue<Boolean> call(CellDataFeatures<Person,Boolean> cdf)
    {
        TableView<Person> tblView = cdf.getTableView();

        Person rowData = cdf.getValue();

        int rowIndex = tblView.getItems().index( rowData );

        return selectedRowList.get( rowIndex );
    }
}

select_col.setCellFactory(
    CheckBoxTableCell.forTableColumn(selectedStateSelectColumn));

这些代码片段确实对我有用.它只需要进行重组以进行编译和运行.但是,基本部分是正确的.

These snippet does work for me. It just needs to be reorganise to compile and run. However, the essentials part are correct.

这个问题或情况非常普遍,但是我花了几天的时间来实施和解决.我希望这对其他人有好处.

This problem or situation is very common, yet it took me days to implement and solve. I hope this serve well for others.

这篇关于请说明如何使用CheckBoxTableCell的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆