JavaFX TableView 触发 css ":filled"-Pseudo-class onScrolling
JavaFX TableView triggers css ":filled"-Pseudo-class onScrolling
当我在 JavaFX8 TableView 中上下滚动时,越来越多的单元格被错误地着色。它接缝 css-pseudo-class ":filled" 被触发,尽管单元格应该是空的。我无法确定关联的 cellValueFactory 是否行为不当,或者某处是否有错误。
this is how it looks after scrolling a while
.css
error-cell:filled {
-fx-background-color: #ff3333;
-fx-text-fill: white;
-fx-opacity: 1;
}
.fxml
<BorderPane fx:id="projectList" stylesheets="@../css/projectList.css,@../css/tables.css" xmlns="http://javafx.com/javafx/8.0.45" xmlns:fx="http://javafx.com/fxml/1" fx:controller="my.package.ProjectListController">
<center>
<TableView fx:id="projectListTableView">
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
<columns>
<TableColumn fx:id="errorCol" styleClass="error-cell" text="Error">
<cellValueFactory>
<PropertyValueFactory property="error" />
</cellValueFactory>
</TableColumn>
</columns>
</TableView>
</center>
</BorderPane>
.java
public class ProjectListController
{
@FXML
private TableView<ProjectWrapper> projectListTableView;
@FXML
private TableColumn<ProjectWrapper, String> errorCol;
private ObservableList<ProjectWrapper> projectTable = FXCollections.observableArrayList();
// dummy-method that fills projectTable, normally it's a db-query
public void fillErrorColumn()
{
ProjectWrapper pw = new ProjectWrapper();
pw.setError("1/0/0");
this.projectTable.add(pw);
}
public void populateTable()
{
try
{
projectListTableView.setItems(this.projectTable);
}
catch (Exception e)
{
logger.error("", e);
}
}
}
你们中有人能想出导致这种行为的原因吗?或者确保单元格在滚动期间保持空白的方法?
顺便说一句,我宁愿不设置额外的 cellValueFactory,因为类似的指标太多了。我也试过了 - 意思是一样的结果。
private void setCellFactoryErrorCol()
{
errorCol.setCellFactory(column ->
{
return new TableCell<ProjectWrapper, String>()
{
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
if (item != null && item.length() > 2)
{
setText(item); // ohne setText() bleibt das Feld
// leer - wird nicht automatisch von
// super gesetzt
getStyleClass().add("error-cell");
setTooltip(new Tooltip("All/In work/Fixed"));
}
else
{
setText(null);
setStyle("");
}
}
};
});
}
非常感谢!
编辑 1
我可以使用 "James_D"s 的回答中的代码来解决我的问题。
尽管我宁愿使用 CSS。
编辑 2
为了最小化 loc 并增强整体可维护性,我创建了一个在控制器初始化期间调用的 utilityClass。
public class CellFactoryUtil
{
public <E> void setCellFactoryStringErrorCol(TableColumn<E, String> errorCol)
{
PseudoClass errorPC = PseudoClass.getPseudoClass("error-pc");
errorCol.setCellFactory(column -> new TableCell<E, String>()
{
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
if (item != null && item.length() > 2)
{
setText(item);
pseudoClassStateChanged(errorPC, true);
setTooltip(new Tooltip("All/In work/Fixed"));
}
else
{
setText(null);
pseudoClassStateChanged(errorPC, false);
}
}
}
);
}
}
我正在使用泛型,因为该程序有几个包含不同包装器的表。仍然有很多代码,但它工作得很好!
对于 CSS,您正在将样式 class 应用到 TableColumn
:目前还不清楚它是如何工作的。 JavaFX CSS guide 中没有 TableColumn
的文档。做到这一点的方法是使用细胞工厂。
请注意,:filled
伪 class 与 :empty
正好相反:即它适用于除空 "space filler" 单元格之外的所有单元格table 但是在实际有数据的行下面。对于行中有数据的所有单元格,:filled
应该是 true
,即使单元格数据是 null
(当然如果单元格数据是空字符串)。
在您的单元工厂实施中,您永远不会从 class 样式列表中删除 "error-cell"
样式 class。此外,当您滚动时,您可能会将字符串 "error-cell"
的多个副本添加到样式列表 classes (可能导致内存泄漏)。
你需要这样的东西
errorCol.setCellFactory(column ->
{
return new TableCell<ProjectWrapper, String>()
{
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
if (item != null && item.length() > 2)
{
setText(item); // ohne setText() bleibt das Feld
// leer - wird nicht automatisch von
// super gesetzt
if (! getStyleClass().contains("error-cell")) {
getStyleClass().add("error-cell");
}
setTooltip(new Tooltip("All/In work/Fixed"));
}
else
{
setText(null);
setStyle(""); // not sure this line does anything: you never set the style anyway...
getStyleClass().remove("error-cell");
}
}
};
});
请注意,为此创建您自己的伪 class 可能更简洁,而不是操纵样式 class:
PseudoClass errorPC = PseudoClass.getPseudoClass("error");
errorCol.setCellFactory(column -> new TableCell<ProjectWrapper, String>() {
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
if (item != null && item.length() > 2)
{
setText(item); // ohne setText() bleibt das Feld
// leer - wird nicht automatisch von
// super gesetzt
pseudoClassStateChanged(errorPC, true);
setTooltip(new Tooltip("All/In work/Fixed"));
}
else
{
setText(null);
pseudoClassStateChanged(errorPC, false);
}
}
});
然后 CSS 看起来像
.table-cell:error {
-fx-background-color: #ff3333;
-fx-text-fill: white;
-fx-opacity: 1;
}
当我在 JavaFX8 TableView 中上下滚动时,越来越多的单元格被错误地着色。它接缝 css-pseudo-class ":filled" 被触发,尽管单元格应该是空的。我无法确定关联的 cellValueFactory 是否行为不当,或者某处是否有错误。
this is how it looks after scrolling a while
.css
error-cell:filled {
-fx-background-color: #ff3333;
-fx-text-fill: white;
-fx-opacity: 1;
}
.fxml
<BorderPane fx:id="projectList" stylesheets="@../css/projectList.css,@../css/tables.css" xmlns="http://javafx.com/javafx/8.0.45" xmlns:fx="http://javafx.com/fxml/1" fx:controller="my.package.ProjectListController">
<center>
<TableView fx:id="projectListTableView">
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
<columns>
<TableColumn fx:id="errorCol" styleClass="error-cell" text="Error">
<cellValueFactory>
<PropertyValueFactory property="error" />
</cellValueFactory>
</TableColumn>
</columns>
</TableView>
</center>
</BorderPane>
.java
public class ProjectListController
{
@FXML
private TableView<ProjectWrapper> projectListTableView;
@FXML
private TableColumn<ProjectWrapper, String> errorCol;
private ObservableList<ProjectWrapper> projectTable = FXCollections.observableArrayList();
// dummy-method that fills projectTable, normally it's a db-query
public void fillErrorColumn()
{
ProjectWrapper pw = new ProjectWrapper();
pw.setError("1/0/0");
this.projectTable.add(pw);
}
public void populateTable()
{
try
{
projectListTableView.setItems(this.projectTable);
}
catch (Exception e)
{
logger.error("", e);
}
}
}
你们中有人能想出导致这种行为的原因吗?或者确保单元格在滚动期间保持空白的方法?
顺便说一句,我宁愿不设置额外的 cellValueFactory,因为类似的指标太多了。我也试过了 - 意思是一样的结果。
private void setCellFactoryErrorCol()
{
errorCol.setCellFactory(column ->
{
return new TableCell<ProjectWrapper, String>()
{
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
if (item != null && item.length() > 2)
{
setText(item); // ohne setText() bleibt das Feld
// leer - wird nicht automatisch von
// super gesetzt
getStyleClass().add("error-cell");
setTooltip(new Tooltip("All/In work/Fixed"));
}
else
{
setText(null);
setStyle("");
}
}
};
});
}
非常感谢!
编辑 1 我可以使用 "James_D"s 的回答中的代码来解决我的问题。 尽管我宁愿使用 CSS。
编辑 2 为了最小化 loc 并增强整体可维护性,我创建了一个在控制器初始化期间调用的 utilityClass。
public class CellFactoryUtil
{
public <E> void setCellFactoryStringErrorCol(TableColumn<E, String> errorCol)
{
PseudoClass errorPC = PseudoClass.getPseudoClass("error-pc");
errorCol.setCellFactory(column -> new TableCell<E, String>()
{
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
if (item != null && item.length() > 2)
{
setText(item);
pseudoClassStateChanged(errorPC, true);
setTooltip(new Tooltip("All/In work/Fixed"));
}
else
{
setText(null);
pseudoClassStateChanged(errorPC, false);
}
}
}
);
}
}
我正在使用泛型,因为该程序有几个包含不同包装器的表。仍然有很多代码,但它工作得很好!
对于 CSS,您正在将样式 class 应用到 TableColumn
:目前还不清楚它是如何工作的。 JavaFX CSS guide 中没有 TableColumn
的文档。做到这一点的方法是使用细胞工厂。
请注意,:filled
伪 class 与 :empty
正好相反:即它适用于除空 "space filler" 单元格之外的所有单元格table 但是在实际有数据的行下面。对于行中有数据的所有单元格,:filled
应该是 true
,即使单元格数据是 null
(当然如果单元格数据是空字符串)。
在您的单元工厂实施中,您永远不会从 class 样式列表中删除 "error-cell"
样式 class。此外,当您滚动时,您可能会将字符串 "error-cell"
的多个副本添加到样式列表 classes (可能导致内存泄漏)。
你需要这样的东西
errorCol.setCellFactory(column ->
{
return new TableCell<ProjectWrapper, String>()
{
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
if (item != null && item.length() > 2)
{
setText(item); // ohne setText() bleibt das Feld
// leer - wird nicht automatisch von
// super gesetzt
if (! getStyleClass().contains("error-cell")) {
getStyleClass().add("error-cell");
}
setTooltip(new Tooltip("All/In work/Fixed"));
}
else
{
setText(null);
setStyle(""); // not sure this line does anything: you never set the style anyway...
getStyleClass().remove("error-cell");
}
}
};
});
请注意,为此创建您自己的伪 class 可能更简洁,而不是操纵样式 class:
PseudoClass errorPC = PseudoClass.getPseudoClass("error");
errorCol.setCellFactory(column -> new TableCell<ProjectWrapper, String>() {
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
if (item != null && item.length() > 2)
{
setText(item); // ohne setText() bleibt das Feld
// leer - wird nicht automatisch von
// super gesetzt
pseudoClassStateChanged(errorPC, true);
setTooltip(new Tooltip("All/In work/Fixed"));
}
else
{
setText(null);
pseudoClassStateChanged(errorPC, false);
}
}
});
然后 CSS 看起来像
.table-cell:error {
-fx-background-color: #ff3333;
-fx-text-fill: white;
-fx-opacity: 1;
}