#css #javafx #tableview #pseudo-class
#css #javafx #tableview #псевдокласс
Вопрос:
когда я прокручиваю вверх и вниз в JavaFX8 TableView, все больше и больше ячеек неправомерно окрашиваются. Это означает, что css-псевдокласс «: заполненный» запускается, хотя ячейка должна быть пустой. Я не могу понять, отсутствует ли связанный cellValueFactory или где-то есть ошибка.
вот как это выглядит после прокрутки некоторое время
.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 amp;amp; 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». Хотя я бы предпочел использовать CSS.
Редактировать 2 Чтобы минимизировать loc и повысить общую удобство обслуживания, я создал класс утилит, который я вызываю во время инициализации контроллеров.
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 amp;amp; item.length() > 2)
{
setText(item);
pseudoClassStateChanged(errorPC, true);
setTooltip(new Tooltip("All/In work/Fixed"));
}
else
{
setText(null);
pseudoClassStateChanged(errorPC, false);
}
}
}
);
}
}
Я использую дженерики, потому что в программе есть несколько таблиц с разными оболочками. Все еще много кода, но он работает просто отлично!
Комментарии:
1. Ну, вы все еще используете CSS с моим решением, нет? И у вас есть дополнительная функциональность на фабрике ячеек, которую вы не смогли бы реализовать без фабрики ячеек (всплывающая подсказка и отсутствие отображения значений с длиной <= 2), поэтому вам уже нужна фабрика ячеек. Не совсем уверен, что именно вы предпочли бы сделать.
Ответ №1:
Для CSS вы применяете класс style к TableColumn
: не совсем понятно, как это будет работать. В руководстве по JavaFX CSS для нет документации TableColumn
. Способ сделать это — использовать фабрику ячеек.
Обратите внимание, что :filled
псевдокласс прямо противоположен :empty
: т. Е. Он верен для всех ячеек, кроме пустых ячеек «заполнителя пространства», которые находятся в таблице, но под строками, которые на самом деле содержат данные. :filled
должно быть true
для всех ячеек, в строках которых есть данные, даже если данные ячейки есть null
(и, конечно, если данные ячейки представляют собой пустую строку).
В вашей реализации cell factory вы никогда не удаляете "error-cell"
класс style из списка классов стилей. Более того, при прокрутке вы, скорее всего, добавите несколько копий строки "error-cell"
в список классов стилей (что может привести к утечке памяти).
Вам нужно что-то вроде
errorCol.setCellFactory(column ->
{
return new TableCell<ProjectWrapper, String>()
{
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
if (item != null amp;amp; 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");
}
}
};
});
Обратите внимание, что для этого может быть проще создать свой собственный псевдокласс, вместо того, чтобы манипулировать классом стиля:
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 amp;amp; 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;
}
Комментарии:
1. Ваше обновление отлично работает! Еще раз спасибо за быстрый и глубокий ответ.