我在javafx中使用自定义单元工厂根据警报状态设置单元格样式,该状态基于现在的时间和检查时间。
一切正常,但我也希望添加一个淡入淡出过渡或其他东西,这将使行基本上闪烁,直到通过更改检查时间来确认。
它比我想要添加大量代码要复杂一些,所以我将发布我的单元工厂类
public class FormattedTableCellFactory<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {
private TableCell<S, T> cell = null;
private FadeTransition ft;
public FormattedTableCellFactory() {
}
@Override
public TableCell<S, T> call(TableColumn<S, T> p) {
cell = new TableCell<S, T>() {
@Override
protected void updateItem(Object item, boolean empty) {
super.updateItem((T) item, empty);
// CSS Styles
String cssStyle;
Person person = null;
if(getTableRow() != null ) {
person = (Person) getTableRow().getItem();
}
ft = new FadeTransition(Duration.millis(500), cell);
ft.setFromValue(1.0);
ft.setToValue(0.1);
ft.setCycleCount(Timeline.INDEFINITE);
ft.setAutoReverse(true);
//Remove all previously assigned CSS styles from the cell.
//Determine how to format the cell based on the status of the container.
if(person != null){
switch(PersonAlert.getAlert(person)){
case WARNING:
ft.stop();
cssStyle = "warning";
break;
case PAST_DUE:
ft.stop();
cssStyle = "pastdue";
break;
case ERC_PAST_DUE:
ft.stop();
cssStyle = "ercpastdue";
break;
case OVERDUE:
ft.playFromStart();
cssStyle = "overdue";
break;
case OVERNIGHT:
ft.stop();
cssStyle = "overnight";
break;
default:
ft.stop();
cssStyle = "normal";
break;
}
}else{
ft.stop();
setText("");
return;
}
//Set the CSS style on the cell and set the cell's text.
getStyleClass().setAll(cssStyle);
if(item != null) {
setText(item.toString());
}else{
setText("");
}
}
};
return cell;
}
}
此代码正常工作,只要此人具有特定状态,单元格的颜色将适当更改。这里唯一的问题是淡入淡出过渡,无论何时第一次运行,淡入淡出过渡运行正常,但当它变为不同的样式时,它不会停止并保持闪烁。
我无法让淡入淡出过渡停止。我相信这是因为每次调用此updateItem时,它都会创建一个我的淡入淡出过渡的新实例,因此当它调用stop时,它会在当前过渡而不是前一个过渡时调用它。我试图通过初始化顶部的过渡来消除这种情况,但它甚至不会闪烁。
所以我的问题是,如何在调用停止时编辑这个以使淡入淡出过渡停止,或者是否有一种不同的方法可以使用单元工厂使单元格/行“闪烁”?
答案 0 :(得分:0)
你把事情放在了错误的水平。
每个单元格应该有一个淡入淡出过渡。目前,每次在单元格上调用 updateItem()
时,都会创建一个新的淡入淡出过渡。您为整个工厂保留一个参考(只需一个参考,无论创建多少个单元格),这只会参考最近创建的淡入淡出过渡。
您同样在工厂中保留了对最近创建的单元格的引用,但出于某种原因,(可能很幸运)您从未实际使用它。
还有一些需要注意的事项:调用getStyleClass().setAll(...)
并不是一个好主意,因为这会删除单元格中的所有默认样式类(例如.table-cell
),这可能会产生影响删除所有默认样式处理。样式类有点难以处理,因为它们是作为列表实现的,但是你应该删除所有出现的那些你不想明确的那些,并确保你不添加你想要的那些副本(除非你真的打算这样做)。此外,您假设(通过强制转换)表视图的类型为Person
,因此将行类型设为通用没有意义。
所以,虽然我不可能测试,因为你没有提供任何代码来测试,你可能想要这些内容:
import java.util.Arrays;
import java.util.List;
import javafx.animation.FadeTransition;
import javafx.animation.Timeline;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.util.Callback;
import javafx.util.Duration;
public class FormattedTableCellFactory<T> implements Callback<TableColumn<Person, T>, TableCell<Person, T>> {
private static final List<String> ALL_STYLES = Arrays.asList(
"warning", "pastdue", "ercpastdue", "overnight", "normal"
);
@Override
public TableCell<Person, T> call(TableColumn<Person, T> p) {
TableCell<Person, T> cell = new TableCell<Person, T>() {
private FadeTransition ft ;
{
ft = new FadeTransition(Duration.millis(500), this);
ft.setFromValue(1.0);
ft.setToValue(0.1);
ft.setCycleCount(Timeline.INDEFINITE);
ft.setAutoReverse(true);
}
@Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
// CSS Styles
String cssStyle = "";
Person person = null;
if(! isEmpty() ) {
// avoid casting here, if you prefer:
person = getTableView().getItems().get(getIndex());
}
//Remove all previously assigned CSS styles from the cell.
getStyleClass().removeAll(ALL_STYLES);
//Determine how to format the cell based on the status of the container.
if(person != null){
switch(PersonAlert.getAlert(person)){
case WARNING:
ft.stop();
setOpacity(1.0);
cssStyle = "warning";
break;
case PAST_DUE:
ft.stop();
setOpacity(1.0);
cssStyle = "pastdue";
break;
case ERC_PAST_DUE:
ft.stop();
setOpacity(1.0);
cssStyle = "ercpastdue";
break;
case OVERDUE:
ft.playFromStart();
cssStyle = "overdue";
break;
case OVERNIGHT:
ft.stop();
setOpacity(1.0);
cssStyle = "overnight";
break;
default:
ft.stop();
setOpacity(1.0);
cssStyle = "normal";
break;
}
}else{
ft.stop();
setOpacity(1.0);
setText("");
}
//Set the CSS style on the cell and set the cell's text.
if(item != null) {
getStyleClass().add(cssStyle);
setText(item.toString());
}else{
setText("");
}
}
};
return cell;
}
}