问题描述
是否可以设置 ListView 组件的样式,使所有元素都没有阴影背景?
我不是这样的:
而是让它们都像第一项、第三项、第五项等一样。
TIA
解决方法
在默认样式表中,ListCell
的 modena.css
背景颜色由以下代码行控制:
.list-cell,.tree-cell {
-fx-background: -fx-control-inner-background;
-fx-background-color: -fx-background;
-fx-text-fill: -fx-text-background-color;
}
/* ... */
.list-cell:odd {
-fx-background: -fx-control-inner-background-alt;
}
因此要删除奇数单元格的替代颜色(请注意,计数是零索引的,因此奇数单元格是列表视图中的第 2 个、第 4 个等),您只需要包含以下内容在您的外部 CSS 文件中,将奇数单元格的颜色恢复为与偶数单元格相同的颜色:
.list-cell:odd {
-fx-background: -fx-control-inner-background ;
}
如果您需要将其应用于一个特定的 ListView
,您可以在该 ListView
上设置一个 ID:
ListView myListView ;
// ...
myListView.setId("plain-list-view");
然后CSS选择器变成
#plain-list-view .list-cell:odd {
-fx-background: -fx-control-inner-background ;
}
,
您需要创建一个具有非空背景的自定义 ListCell。执行此操作后,所选行的 ListView 的自动颜色处理将不再正常工作。所以你必须自己处理。选择操作会将文本颜色反转为白色,仅此而已。所以需要根据ListCell的“Selected”属性来设置单元格的背景色。在 Java 中,它看起来像这样:
public class Sample1 extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Scene scene = new Scene(new ListBackgroundWhite(),300,200);
primaryStage.setScene(scene);
primaryStage.show();
}
}
public class ListBackgroundWhite extends ListView<String> {
public ListBackgroundWhite() {
super();
setCellFactory(listView -> new WhiteListCell());
setItems(FXCollections.observableArrayList("first line","second line","third line","fourth line"));
}
static class WhiteListCell extends ListCell<String> {
WhiteListCell() {
Background unselectedBackground =
new Background(new BackgroundFill(Color.WHITESMOKE,CornerRadii.EMPTY,Insets.EMPTY));
Background selectedBackground = new Background(new BackgroundFill(Color.BROWN,Insets.EMPTY));
backgroundProperty().bind(Bindings.createObjectBinding(() -> isSelected() ? selectedBackground :
unselectedBackground,selectedProperty()));
}
@Override
public void updateItem(String item,boolean isEmpty) {
super.updateItem(item,isEmpty);
if (!isEmpty) {
setText(item);
} else {
setText(null);
}
}
}
}
一旦你这样做,单元格背景不再透明,ListView本身的条纹图案也不会显示出来。
编辑:
正如所指出的,这是严厉的,除了在大多数情况下 ListView 不会是一个简单的带有字符串的标签。它将在 ListCell 中具有某种布局,这将要求您在任何情况下创建自定义 ListCell。
然而,通过绑定到“Selected”属性直接弄乱背景是笨拙的。可以新建一个StyleClass,然后在css中定义修改后的PseudoClasses即可。然后将这个新的 StyleClass 添加到自定义 ListCell 中,然后它会在应用“EVEN”和“ODD”伪类时自动处理它。
我发现的一件事是,由于在默认 Modena css 中的所有其他定义之后应用了新的“奇数”定义,因此抑制了奇数行的“SELECTED”伪类。这意味着奇数行和偶数行在选择时看起来不同,因此需要在“ODD”定义之后将重复的“SELECTED”定义添加到新css中。然后一切正常。所以新代码看起来像这样:
CSS:
.custom-list-cell:odd {
-fx-background: -fx-control-inner-background;
}
.custom-list-cell:selected {
-fx-background: -fx-selection-bar;
-fx-table-cell-border-color: derive(-fx-selection-bar,20%);
}
主要,现在将新样式表加载到场景中:
public class Sample1 extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Scene scene = new Scene(new ListBackgroundWhite(),200);
scene.getStylesheets().add(getClass().getResource("/css/samples.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
}
然后对 ListCell 的唯一自定义是添加新的 StyleClass:
public class ListBackgroundWhite extends ListView<String> {
public ListBackgroundWhite() {
super();
setCellFactory(listView -> new WhiteListCell());
setItems(FXCollections.observableArrayList("first line","fourth line"));
}
static class WhiteListCell extends ListCell<String> {
WhiteListCell() {
getStyleClass().add("custom-list-cell");
}
@Override
public void updateItem(String item,boolean isEmpty) {
super.updateItem(item,isEmpty);
if (!isEmpty) {
setText(item);
} else {
setText(null);
}
}
}
}
但如果你真的只想拥有一个只有简单标签的 ListView,你可以让单元工厂将 StyleClass 添加到标准 TextFieldListCell 上:
public ListBackgroundWhite() {
super();
setCellFactory(listView -> {
ListCell<String> cell = new TextFieldListCell<>();
cell.getStyleClass().add("custom-list-cell");
return cell;
});
setItems(FXCollections.observableArrayList("first line","fourth line"));
}