如何使用css在JavaFX中更改ListView单元格的文本颜色

时间:2016-06-20 19:15:39

标签: java css javafx javafx-2

所以我有一个列表,里面装满了我的数据库中的名字。这些名称代表在公司工作或曾经工作过的员工。我已经看到可以改变单元格的文本颜色,但是当我应用它时,它会改变所有这些颜色。我真正想要的是改变不再工作的客户的颜色。

我在List中添加了“not active”,因此我可以将“active”和“not active”客户端分开。

以下是我在ArrayList中添加员工姓名的代码:

public  ArrayList<String> search(String unit, String name)
    {
        ArrayList<String> temp= new ArrayList<String>();
        String sql="";
        if(unit=="all units")
            sql="SELECT * FROM employees WHERE name='"+name+"';";
        else
            sql="SELECT * FROM employees WHERE unit='"+unit+"' AND name='"+name+"';";
        try {
        ResultSet rs=bp.select(sql);
            while(rs.next())
            {
                if(rs.getInt("active")==1)
                temp.add(rs.getString("name"));
                else
                    temp.add(rs.getString("name")+" - not active");
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Collections.sort(temp);
        return temp;
    }

以下是我在ListView中添加ArrayList的代码:

for (String item: u.search(unitCB.getValue(),nameTF.getText()))
                            SearchLW.getItems().add(item);

现在,我觉得是否可以使用css更改此列表中的文本颜色,以便所有不活跃的员工使用红色?如果不是,关于如何更改此特定ListView单元格的文本颜色的另一种解决方案将会有所帮助。

2 个答案:

答案 0 :(得分:2)

您可以使用CSS伪类来表示“非活动”样式,并在CSS文件中设置样式。使用您当前的代码,它看起来像:

ListView<String> listView = new ListView<>();
PseudoClass inactive = PseudoClass.getPseudoClass("inactive");
listView.setCellFactory(lv -> new ListCell<String>() {
    @Override
    protected void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);
        setText(empty ? null : item);
        pseudoClassStateChanged(inactive, item != null && item.endsWith(" - not active"));
    }
});

然后在外部css文件中,您可以定义所需的样式:

.list-cell:inactive {
    -fx-text-fill: red ;
}

在这里测试字符串值非常脆弱(想象一下如果你试图将应用程序国际化,或者当你的老板告诉你改变演示文稿以便"not active"在括号中,或者其他什么时会发生什么...... )。我建议创建一个Employee类:

public class Employee {
    private final String name ;
    private final boolean active ;

    public Employee(String name, boolean active) {
        this.name = name ;
        this.active = active ;
    }

    public String getName() {
        return name ;
    }

    public boolean isActive() {
        return active ;
    }
}

然后你做

ListView<Employee> listView = new ListView<>();
PseudoClass inactive = PseudoClass.getPseudoClass("inactive");
listView.setCellFactory(lv -> new ListCell<Employee>() {
    @Override
    protected void updateItem(Employee employee, boolean empty) {
        super.updateItem(employee, empty);
        if (empty) {
            setText(null);
            pseudoClassStateChanged(inactive, false);
        } else {
            if (employee.isActive()) {
                setText(employee.getName());
                pseudoClassStateChanged(inactive, false);
            } else {
                setText(employee.getName() + " - not active");
                pseudoClassStateChanged(inactive, true);
            }
        }
    }
});

并对您发布的方法进行明显更新:

public  ArrayList<Employee> search(String unit, String name) {
    ArrayList<Employee> temp= new ArrayList<>();
    String sql="SELECT * FROM employees WHERE unit like ? AND name=?";

    try (PreparedStatement pStmnt = conn.prepareStatement(sql)) {

        if("all units".equals(unit))
            pStmnt.setString(1, "%");
        else
            pStmnt.setString(1, unit);

        pStmnt.setString(2, name);
        ResultSet rs=pStmnt.executeQuery();
        while(rs.next())
        {
            temp.add(new Employee(rs.getString("name"), rs.getInt("active")==1);
        }
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    temp.sort(Comparator.comparing(Employee::getName));
    return temp;
}

答案 1 :(得分:2)

这是一个替代实现,它只使用样式类而不是伪类。在这种情况下,伪类实现可能更好。

虽然,或许这个解决方案可能会扩展得更好一些,因为您可以为选定的vs未选中或聚焦与未聚焦的单元格指定单独的伪类样式,如果使用自定义伪类,这可能很难(虽然我不确定。)

activity

ActivityListViewer.java

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;

public class ActivityListViewer extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        ListView<Activity> activityListView = new ListView<>(
                FXCollections.observableArrayList(
                        new Activity("Fetch super suit from drycleaner", false),
                        new Activity("Interview governor with Jimmy", false),
                        new Activity("Rescue stranded kitten", true),
                        new Activity("Dinner date with Lois", false)
                )
        );

        activityListView.setCellFactory(param -> new ListCell<Activity>() {
            static final String ACTIVE_CLASS = "active";
            @Override
            protected void updateItem(Activity item, boolean empty) {
                super.updateItem(item, empty);

                if (empty || item == null || item.getName() == null) {
                    setText(null);
                    getStyleClass().remove(ACTIVE_CLASS);
                } else {
                    if (item.isActive()) {
                        setText(item.getName() + " - active");
                    } else {
                        setText(item.getName());
                    }

                    if (item.isActive() && !getStyleClass().contains(ACTIVE_CLASS)) {
                        getStyleClass().add(ACTIVE_CLASS);
                    } else {
                        getStyleClass().remove(ACTIVE_CLASS);
                    }
                }
            }
        });

        activityListView.setPrefHeight(150);

        Scene scene = new Scene(activityListView);
        scene.getStylesheets().add(
                this.getClass().getResource("activity.css").toExternalForm()
        );

        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

class Activity {
    private final StringProperty nameProperty;
    private final BooleanProperty activeProperty;

    public Activity(String name, boolean active) {
        this.nameProperty = new SimpleStringProperty(name);
        this.activeProperty = new SimpleBooleanProperty(active);
    }

    public String getName() {
        return nameProperty.get();
    }

    public StringProperty nameProperty() {
        return nameProperty;
    }

    public boolean isActive() {
        return activeProperty.getValue() != null
                ? activeProperty.getValue()
                : false;
    }

    public BooleanProperty activeProperty() {
        return activeProperty;
    }
}

activity.css

.active {
    -fx-text-fill: forestgreen;
}

.active:selected {
    -fx-text-fill: lawngreen;
}