Module  javafx.controls
软件包  javafx.scene.control

Class Cell<T>

  • 参数类型
    T - 单元格中包含的项目的类型。
    All Implemented Interfaces:
    StyleableEventTargetSkinnable
    已知直接子类:
    DateCellIndexedCell


    public class Cell<T>
    extends Labeled
    细胞API被用于如虚拟化控制ListViewTreeView ,和TableView 单元格是Labeled Control ,用于在ListView,TreeView或TableView中呈现单个“行”。 单元格也用于TableView内的每个单独的单元格(即每行/列交点)。 有关详细信息,请分别参阅JavaDoc的每个控件。

    每个单元格与单个数据项(由item属性表示)相关联。 单元格负责渲染该项目,并在适当情况下负责编辑该项目。 小区内的一个项目可以由文本或一些其它控制,例如一个来表示CheckBoxChoiceBox或任何其他Node诸如HBoxGridPane ,或甚至是Rectangle

    因为TreeView,ListView,TableView和其他这样的控件可能潜在地用于显示非常大量的数据,所以不可能为控件中的每个项目创建一个实际的单元格。 我们只使用很少的单元格代表非常大的数据集。 每个Cell都被“回收”,或重用。 当我们说这些控件被虚拟化时,这就是我们的意思。

    由于Cell是一个控件,它本质上是一个“模型”。 它的皮肤负责定义外观和布局,而行为负责处理所有输入事件并使用该信息来修改控制状态。 另外,像任何其他控件一样,单元格从CSS样式。 然而,对于Cell的大多数使用,不需要实施Skin。 这是因为一个电池厂可以设置 - 这很详细。

    因为到目前为止,单元格最常用的用例是向用户显示文本,这种用例是针对单元格进行了特别优化的。 这是由细胞从Labeled延伸完成的。 这意味着Cell的子类只需要设置text属性,而不是创建一个单独的Label并在Cell中进行设置。 然而,对于不仅仅需要纯文本的事情,可以在Cell graphic属性中放置任何Node 尽管这个术语,图形可以是任何节点,并将完全交互。 例如,ListCell可能配置为Button作为其图形。 然后可以将按钮文本绑定到单元格item属性。 这样,只要单元格中的项目更改,Button文本就会自动更新。

    单元格集focusTraversable为false。

    电池厂

    Cell item的默认表示item各种虚拟化容器的外观。 例如,默认情况下,ListView会将该项目转换为字符串,并使用此值调用Labeled.setText(java.lang.String) 如果要专门为ListView使用的单元格(例如),则必须提供在ListView上定义的cellFactory回调函数的实现。 类似的API存在于使用的细胞(例如大多数控件, TreeViewTableViewTableColumnListView

    当它确定需要创建一个新的单元格时,该平台将调用该单元格工厂。 例如,也许您的ListView有1000万项。 创建所有1000万个单元格将是非常昂贵的。 因此,ListView皮肤实现可能只创建足够的单元格来适应视觉空间。 如果将ListView的大小调整为较大,系统将确定需要创建一些其他单元格。 在这种情况下,它将调用cellFactory回调函数(如果提供一个)来创建应该使用的Cell实现。 如果没有提供单元格工厂,将使用内置的默认实现。

    然后,单元工厂的实现不仅仅用于创建单元实例,还负责配置该单元格,使其对其状态的变化作出反应。 例如,如果我要创建一个格式化数字的自定义单元格,以便它们显示为货币类型,我可能会这样做:

      public class MoneyFormatCell extends ListCell<Number> {
    
         public MoneyFormatCell() {    }
    
         @Override protected void updateItem(Number item, boolean empty) {
             // calling super here is very important - don't skip this!
             super.updateItem(item, empty);
    
             // format the number as if it were a monetary value using the
             // formatting relevant to the current locale. This would format
             // 43.68 as "$43.68", and -23.67 as "-$23.67"
             setText(item == null ? "" : NumberFormat.getCurrencyInstance().format(item));
    
             // change the text fill based on whether it is positive (green)
             // or negative (red). If the cell is selected, the text will
             // always be white (so that it can be read against the blue
             // background), and if the value is zero, we'll make it black.
             if (item != null) {
                 double value = item.doubleValue();
                 setTextFill(isSelected() ? Color.WHITE :
                     value == 0 ? Color.BLACK :
                     value < 0 ? Color.RED : Color.GREEN);
             }
         }
     } 
    这个类可以在ListView中被使用:
      ObservableList<Number> money = ...;
     final ListView<Number> listView = new ListView<Number>(money);
     listView.setCellFactory(new Callback<ListView<Number>, ListCell<Number>>() {
         @Override public ListCell<Number> call(ListView<Number> list) {
             return new MoneyFormatCell();
         }
     }); 
    在这个例子中,创建一个匿名内部类,只要它被调用时就简单地返回MoneyFormatCell的实例。 MoneyFormatCell类扩展了ListCell ,覆盖了updateItem方法。 当单元格中的项目更改时,就会调用此方法,例如,当用户滚动ListView或底层数据模型的内容时,会更改(并且单元格重用于在ListView中表示某些不同的项目)。 因此,不需要管理绑定 - 只要在发生此方法时对项目的更改做出反应。 在上面的示例中,每当项目更改时,我们更新单元格文本属性,并修改文本填充,以确保我们获得正确的视觉效果。 另外,如果单元格是“空”(意思是用于填写ListView中的空格,但没有与之相关联的任何数据),那么我们只使用空字符串。

    请注意,还有一些额外的方法以'update'为前缀可能是有意义的,因此请务必仔细阅读Cell的Cell文档和Cell的子类。

    当然,我们也可以使用绑定API而不是覆盖'update'方法。 下面显示的是一个非常简单的例子,说明如何实现这一点。

      public class BoundLabelCell extends ListCell<String> {
    
         public BoundLabelCell() {
             textProperty().bind(itemProperty());
         }
     } 

    主要设计目标

    • 对于大型数据集,时间和记忆都是有效的
    • 易于构建和使用自定义单元格的库
    • 容易定制细胞视觉效果
    • 易于自定义显示格式(12.34为$ 12.34或1234%等)
    • 轻松扩展自定义视觉效果
    • 易于拥有“面板”的数据视觉效果
    • 易于动画的细胞大小或其他属性

    关键用例

    以下是用于驱动Cell API设计的一些关键用例,以及显示这些API如何满足这些用例的代码示例。 这绝对不能被视为支持的功能或功能的确定列表,而是提供关于如何使用Cell API的一些指导。 以下示例集中在ListView上,但同样的理念适用于TreeCells或其他类型的单元格。

    更改单元格的颜色

    这在JavaFX中应该非常简单。 每个单元格可以直接从CSS样式。 所以例如,如果您想将ListView中每个单元格的默认背景更改为WHITE,您可以执行以下CSS:

      .list-cell {
       -fx-padding: 3 3 3 3;
       -fx-background-color: white;
     } 
    如果要将所选ListView单元格的颜色设置为蓝色,可以将其添加到CSS文件中:
      .list-cell:selected {
       -fx-background-color: blue;
     } 
    大多数Cell实现从IndexedCell而不是Cell扩展。 IndexedCell增加了另外两个伪类:“奇”和“偶”。 使用这个可以通过在CSS文件中执行这样的操作来获得替代行条带:
      .list-cell:odd {
       -fx-background-color: grey;
     } 
    这些示例中的每一个都不需要更改代码。 只需更新您的CSS文件来改变颜色。 您也可以使用CSS中的“hover”和其他伪类与其他控件相同。

    上面第一个例子的另一种方法(格式化数字列表)将是使用样式类。 假设你有一个ObservableList的Numbers要显示在ListView中,并且想要将所有的负值都设为红色,所有的正值或者0值都是黑色的。 实现这一点的一种方法是使用自定义的cellFactory,它可以根据值为负还是正值来更改单元格的styleClass。 这样添加代码来测试单元格中的数字是否为负数,并添加一个“负”样式类。 如果数字不是负数,则应该删除“否定”字符串。 这种方法允许从CSS定义颜色,允许简单的定制。 CSS文件将包含以下内容:

      .list-cell {
       -fx-text-fill: black;
     }
    
     .list-cell .negative {
       -fx-text-fill: red;
     } 

    编辑

    使用Cell体系结构(例如最虚拟控制ListViewTreeViewTableViewTreeTableView )所有经由细胞直接支持编辑值的概念。 您可以通过上述类文档中的“编辑”部分获取有关控制特定详细信息的更多信息。 本节的其余部分将介绍使用单元格编辑的一些更精细的细节。

    编辑的一般流程如下(注意,在这些步骤中,使用ListView控件作为示例,但对于上述所有控件,存在类似的API,并且整个过程完全相同):

    1. 用户请求单元格进入编辑模式(通过键盘或鼠标命令),或者开发者请求单元格进入编辑模式(通过调用ListView edit方法) 注意:如果用户双击或触发一个适当的键盘命令启动编辑,那么它们就有效地调用了控件上的适当的编辑方法(即用户发起的和开发人员启动的编辑的输入方法是相同的)。
    2. 通知控件可见区域中的每个单元格,当前的editing cell已更改,并检查其是否为自身。 在这一点上,三件事之一可能发生:
      1. 如果编辑索引与单元格索引相同,则在此单元格上将调用startEdit() 一些指针:
        1. 建议当进入编辑状态时,单元格的子类覆盖startEdit()方法来更新单元格的视觉效果。 但是请注意,覆盖startEdit()方法的子类继续调用super.startEdit()非常重要,以便父类可以更新编辑成功所需的附加状态。
        2. startEdit()方法之内是改变细胞视觉效果的理想时间。 例如(请注意,在UI控件的javadoc这个例子更充实为ListView ,等等),你可以设置Labeled.graphicProperty()的细胞对TextField并设置Labeled.textProperty()为null。 这将允许最终用户键入输入并对数据模型进行更改。
        3. 当用户完成编辑时,他们将要提交或取消其更改。 这是您的责任(例如通过输入密钥commit the edit和ESC键cancel the edit )。 您可以通过将适当的事件侦听器附加到在编辑状态下显示的节点。
      2. 如果编辑索引与单元格不一样,并且如果单元格当前在editing state ,则在此单元格上将调用cancelEdit() startEdit()方法一样,您应该覆盖此方法以清理单元格的视觉效果(并且最有可能将Labeled.graphicProperty()返回到null,并将其设置为(可能为新值)为Labeled.textProperty()同样,请务必始终调用super.cancelEdit()确保所有状态正确更新。
      3. 如果编辑指数是不一样的指数作为小区,如果小区是不是目前在isEditing()编辑状态},则什么也不会发生在这个小区。
    从以下版本开始:
    JavaFX 2.0
    • Property Detail

      • item

        public final ObjectProperty<T> itemProperty
        与该单元格相关联的数据值。 当创建或更新单元格时,此值由虚拟控件设置。 这表示原始数据值。

        这个值只能在Cell的子类中被虚拟化的用户界面控件设置,这些控件知道如何正确使用Cell类。

        结果
        与该单元格相关联的数据值
      • empty

        public final ReadOnlyBooleanProperty emptyProperty
        用于表示单元格是否具有任何内容的属性。 如果为true,则Cell不包含数据,并且不与虚拟控件中的任何数据项相关联。

        当单元格为空时,可以通过“空”CSS伪类状态对其进行样式化。 例如,它可能不会接收任何替代行突出显示,或者当悬停时可能不会收到悬停背景填充。

        另请参见:
        isEmpty()
      • selected

        public final ReadOnlyBooleanProperty selectedProperty
        指示此单元格是否已被选中。 例如,ListView将零个或多个单元格定义为“选定”单元格。
        另请参见:
        isSelected()
      • editable

        public final BooleanProperty editableProperty
        表示该单元是否被允许进入编辑状态的属性。 默认情况下,可以在单元格中将editable设置为true(尽管可以允许Cell的子类进入编辑状态,但可能需要满足其他条件,例如,ListCell要求ListView editable属性也为true。
        另请参见:
        isEditable()setEditable(boolean)
    • 构造方法详细信息

      • Cell

        public Cell​()
        创建默认样式类为“单元格”的默认单元格。
    • 方法详细信息

      • itemProperty

        public final ObjectProperty<T> itemProperty​()
        与该单元格相关联的数据值。 当创建或更新单元格时,此值由虚拟控件设置。 这表示原始数据值。

        这个值只能在Cell的子类中被虚拟化的用户界面控件设置,这些控件知道如何正确使用Cell类。

        结果
        与该单元格相关联的数据值
      • setItem

        public final void setItem​(T value)
        将项目设置为给定的值 - 不应该直接调用该项目由虚拟化控件管理。
        参数
        value - 要在此单元格中设置的新数据值
      • getItem

        public final T getItem​()
        返回与该单元格相关联的数据值。
        结果
        与该单元格相关联的数据值
      • emptyProperty

        public final ReadOnlyBooleanProperty emptyProperty​()
        用于表示单元格是否具有任何内容的属性。 如果为true,则Cell不包含数据,并且不与虚拟控件中的任何数据项相关联。

        当单元格为空时,可以通过“空”CSS伪类状态对其进行样式化。 例如,它可能不会接收任何替代行突出显示,或者当悬停时可能不会收到悬停背景填充。

        另请参见:
        isEmpty()
      • isEmpty

        public final boolean isEmpty​()
        返回一个布尔值,表示单元格是否被认为是空的。
        结果
        如果单元格为空,则为true,否则为false
      • selectedProperty

        public final ReadOnlyBooleanProperty selectedProperty​()
        指示此单元格是否已被选中。 例如,ListView将零个或多个单元格定义为“选定”单元格。
        另请参见:
        isSelected()
      • isSelected

        public final boolean isSelected​()
        返回此单元格当前是否被选中。
        结果
        如果选择单元格,则为真,否则为false。
      • isEditing

        public final boolean isEditing​()
        表示单元格当前是否处于编辑状态。
        结果
        如果此单元格当前处于编辑状态,则为true,否则为false
      • setEditable

        public final void setEditable​(boolean value)
        允许某些单元格无法编辑。 这在List表示“标题行”的情况下很有用 - 标题行可以编辑没有意义,因此它们应该具有可编辑设置为false。
        参数
        value - 表示单元格是否可编辑的布尔值。 如果为true,则单元格是可编辑的,如果为false,则不能编辑单元格。
      • isEditable

        public final boolean isEditable​()
        返回此单元格是否被允许进入编辑状态。
        结果
        如果允许这个单元格进入编辑状态,则为true,否则为false
      • editableProperty

        public final BooleanProperty editableProperty​()
        表示该单元是否被允许进入编辑状态的属性。 默认情况下,可以在单元格中将editable设置为true(尽管可以允许Cell的子类进入其编辑状态,但可能需要满足其他条件。例如,ListCell要求ListView editable属性也为true。
        另请参见:
        isEditable()setEditable(boolean)
      • startEdit

        public void startEdit​()
        调用此功能从非编辑状态转换到编辑状态,如果单元格是可编辑的。 如果这个单元格已经处于编辑状态,它将保留在它中。
      • cancelEdit

        public void cancelEdit​()
        调用此功能从编辑状态转换为非编辑状态,而不保存任何用户输入。
      • commitEdit

        public void commitEdit​(T newValue)
        在适当的时候调用此功能(基于您的单元格编辑用户界面的用户交互要求)来做两件事情:
        1. 将适当的事件触发回到支持UI控件(例如ListView )。 这将开始将此编辑推回相关数据源/属性(尽管不能保证这将成功 - 这取决于正在使用的特定编辑提交处理程序)。 有关更多详细信息,请参阅UI控件类javadoc。
        2. 开始从编辑状态转换到非编辑状态。

        一般来说,在自定义单元实现中无需重写此方法 - 在适当的时候简单地调用此方法就足够了(例如,当用户按下Enter键时,可以执行像cell.commitEdit(converter.fromString(textField.getText()));

        参数
        newValue - 作为最终用户输入的值,应该以相关的方式保持给定基于用户界面的数据源和UI控件的安装编辑提交处理程序。
      • layoutChildren

        protected void layoutChildren​()
        在布局传递期间调用这个Parent的孩子。 默认情况下,它只会将受管理的可调整大小的内容的大小设置为其首选大小,并且不会执行任何节点定位。

        子类应该根据需要重写此函数以布局内容。

        重写:
        layoutChildrenControl
      • updateItem

        protected void updateItem​(T item,
                                  boolean empty)
        updateItem方法不应该被开发人员调用,但它是开发人员覆盖的最佳方式,以允许它们自定义单元格的视觉效果。 为了弄清楚,开发人员不应该在他们的代码中调用这个方法(他们应该留给UI控件,比如ListView控件)来调用这个方法。 但是,使用updateItem方法的目的是让开发人员在指定自定义单元格工厂时(再次像ListView cell factory ),可以覆盖updateItem方法以允许对单元格进行完全自定义。

        非常重要的是,Cell的子类会正确覆盖updateItem方法,因为这样做会导致诸如空白单元格或其中出现意外内容的单元格等问题。 以下是如何正确覆盖updateItem方法的示例:

          protected void updateItem(T item, boolean empty) {
             super.updateItem(item, empty);
        
             if (empty || item == null) {
                 setText(null);
                 setGraphic(null);
             } else {
                 setText(item.toString());
             }
         } 

        注意在这段代码示例中的两个重点:

        1. 我们称之为super.updateItem(T,boolean)方法。 如果没有这样做,项目和空属性设置不正确,您可能会遇到图形问题。
        2. 我们测试empty条件,如果为true,我们将文本和图形属性设置为null。 如果我们不这样做,几乎可以保证最终用户意外地看到细胞中的图形工件。
        参数
        item - 单元格的新项目。
        empty - 该单元格是否表示列表中的数据。 如果它是空的,那么它不表示任何域数据,而是用于呈现“空”行的单元格。
      • updateSelected

        public void updateSelected​(boolean selected)
        更新此单元格是否处于选定状态。
        参数
        selected - 是否选择此单元格。
      • isItemChanged

        protected boolean isItemChanged​(T oldItem,
                                        T newItem)
        此方法由Cell子类调用,以便某些CPU密集型操作(具体来说,调用updateItem(Object, boolean) )仅在必要时执行(即,仅当当前设置的item与所提出的新项目不同时才执行设置)。

        此方法的默认实现将针对相等性进行测试,但开发人员可以覆盖此方法,以其他特定于其域的方式执行检查。

        参数
        oldItem - 单元格中包含的当前设置的项目(即它与通过 getItem()可用的项目相同)。
        newItem - 如果此方法返回true,将在单元格中设置的项目。 如果此方法返回false,则可能无法设置。
        结果
        如果新项目被认为与旧项目不同,则返回true。 默认情况下,此方法针对相等性进行测试,但子类可能会更改实现以适应其需求进行测试。
        从以下版本开始:
        JavaFX 8u40
      • getInitialFocusTraversable

        protected Boolean getInitialFocusTraversable​()
        返回此控件的初始焦点遍历状态,供JavaFX CSS引擎正确设置其初始值。 该方法被覆盖,因为默认情况下UI控件将focus遍历设置为true,但这不适用于此控件。
        重写:
        getInitialFocusTraversableControl
        结果
        该控件的初始聚焦可移动状态
        从以下版本开始:
        9