问题描述
我希望在用户删除表行时将其更新为删除线。我是javafx的新手,一直没有运气。
donationsTable.setRowFactory(tv -> {
TableRow<Donation> row = new TableRow<Donation>() {
// to force updateItem called
@Override
protected boolean isItemChanged(Donation d,Donation d2) {
return true;
}
@Override
public void updateItem(Donation d,boolean empty) {
super.updateItem(d,empty) ;
if (d == null) {
setStyle("");
} else if (d.getAction().equals(Donation.DELETE_DONATION)) {
setStyle("delete-row");
} else if (d.getAction().equals(Donation.NEW_DONATION)) {
setStyle("-fx-font-weight: bold;");
} else {
setStyle("");
}
}
};
row.setonMouseClicked(event -> {
deleteDonation.setdisable(false);
});
return row;
});
粗体字用于新捐赠,但我无法删除线起作用。我确实看到需要在文本而不是行上进行设置,所以我的css是:
.delete-row .text {
-fx-strikethrough: true;
}
但是,我收到警告:警告CSS错误,解析'* {delete-row}:在[1,12]处预期冒号 我对CSS仅有一个非常基本的了解。这是我在其他答案中看到的,但是我不明白为什么它对我不起作用。
非常感谢您的帮助。
根据James_D的建议,我更改了updateItem:
public void updateItem(Donation d,empty) ;
PseudoClass delete = PseudoClass.getPseudoClass("delete-row");
pseudoClassstateChanged(delete,d != null && d.getAction().equals(Donation.DELETE_DONATION));
PseudoClass add = PseudoClass.getPseudoClass("add-row");
pseudoClassstateChanged(add,d != null && d.getAction().equals(Donation.NEW_DONATION));
}
css有
.table-row-cell:delete-row .text {
-fx-strikethrough: true;
}
.table-row-cell:add-row {
-fx-font-weight: bold;
}
删除线仍然不起作用,粗体停止工作。
解决方法
setStyle
方法将在Node
上设置内联样式;这种样式采用CSS规则的形式。这是使用粗体显示的情况:
if (d.getAction().equals(Donation.NEW_DONATION)) {
setStyle("-fx-font-weight: bold;");
}
要将CSS类添加到节点的类列表中,请使用getStyleClass()
获取节点的CSS类的列表,然后对其进行操作。
这里您必须要小心一点,因为列表可以包含相同值的多个副本,此外,您无法控制调用updateItem()
的次数以及调用Donation
的次数。作为参数。最好的选择是删除类delete-row
的所有实例,并在正确的条件下重新添加一个实例:
@Override
public void updateItem(Donation d,boolean empty) {
super.updateItem(d,empty) ;
getStyleClass().removeAll(Collections.singleton("delete-row"));
if (d == null) {
setStyle("");
} else if (d.getAction().equals(Donation.DELETE_DONATION)) {
setStyle("");
getStyleClass().add("delete-row");
} else if (d.getAction().equals(Donation.NEW_DONATION)) {
setStyle("-fx-font-weight: bold;");
} else {
setStyle("");
}
}
另一种选择是改用CSS伪类:
@Override
public void updateItem(Donation d,empty) ;
PseudoClass delete = PseudoClass.getPseudoClass("delete-row");
pseudoClassStateChanged(delete,d != null && d.getAction().equals(Donation.DELETE_DONATION));
if (d != null && d.getAction().equals(Donation.NEW_DONATION)) {
setStyle("-fx-font-weight: bold;");
} else {
setStyle("");
}
}
使用
.table-row-cell:delete-row .text {
-fx-strikethrough: true;
}
在这种情况下,为了保持一致性,我可能还会将NEW_DONATION
样式重构为伪类。
这是使用伪类的完整示例。请注意,我将CSS更改为粗体(据我所知,使用font-weight
取决于系统当前所选字体的字体是粗体;还是将通用名称(sans-serif
)与{{1 }}规则更强大。)
Donation.java
-fx-font
App.java
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Donation {
public enum Action { NEW_DONATION,DELETE_DONATION,NO_ACTION }
private final StringProperty name = new SimpleStringProperty() ;
private final ObjectProperty<Action> action = new SimpleObjectProperty<>() ;
public Donation(String name,Action action) {
setName(name);
setAction(action);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final ObjectProperty<Action> actionProperty() {
return this.action;
}
public final Action getAction() {
return this.actionProperty().get();
}
public final void setAction(final Action action) {
this.actionProperty().set(action);
}
}
style.css:
import java.util.Random;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.property.Property;
import javafx.css.PseudoClass;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage stage) {
TableView<Donation> table = new TableView<>();
table.setRowFactory(tv -> {
TableRow<Donation> row = new TableRow<>() {
@Override
protected void updateItem(Donation donation,boolean empty) {
super.updateItem(donation,empty);
PseudoClass add = PseudoClass.getPseudoClass("add-row");
pseudoClassStateChanged(add,donation != null && donation.getAction() == Donation.Action.NEW_DONATION);
PseudoClass delete = PseudoClass.getPseudoClass("delete-row");
pseudoClassStateChanged(delete,donation != null && donation.getAction() == Donation.Action.DELETE_DONATION);
}
};
return row ;
});
Random rng = new Random();
for (int i = 1 ; i <= 40 ; i++) {
table.getItems().add(new Donation("Donation "+i,Donation.Action.values()[rng.nextInt(3)]));
}
table.getColumns().add(column("Donation",Donation::nameProperty));
table.getColumns().add(column("Action",Donation::actionProperty));
BorderPane root = new BorderPane(table);
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
stage.setScene(scene);
stage.show();
}
private static <S,T> TableColumn<S,T> column(String name,Function<S,Property<T>> prop) {
TableColumn<S,T> col = new TableColumn<>(name);
col.setCellValueFactory(data -> prop.apply(data.getValue()));
return col ;
}
public static void main(String[] args) {
launch();
}
}
更新:
如果其中某一列未观察到确定表行样式的属性(例如,在上面的示例中,“ action”列不存在),则需要安排该行观察该属性本身。这有点棘手,因为该行已用于不同的表项,因此您需要在正确的属性中添加和删除侦听器。看起来像:
.table-row-cell:delete-row .text {
-fx-strikethrough: true;
}
.table-row-cell:add-row {
/* -fx-font-weight: bold; */
-fx-font: bold 1em sans-serif ;
}