有没有办法在 JavaFX 中使 ListView 元素加粗?

如何解决有没有办法在 JavaFX 中使 ListView 元素加粗?

所以我是 JavaFX 的新手,我正在制作我的第一个应用程序。我想有一个选项,在选择它并单击按钮后,将我的 ListView 中的元素设为粗体。不幸的是,我找不到任何解决我的问题的方法,而且我没有想法。如果您能告诉我如何在 .java 或 .fxml 文件中执行此操作,我将不胜感激,因为我现在不使用 CSS 文件

enter image description here

解决方法

实现这样的功能需要做一些事情:

  • 适合您的 ListView
  • 的数据模型
  • 用于您的 CellFactory 的自定义 ListView,将修改其中包含的项目的样式
  • 一种更新 Person 模型以将个人标记为“重要”的方法

在此答案的底部有一个完整的示例应用程序(带有注释),但让我们将其分解并解决上述问题。

数据模型:

如果您使用简单的 String 作为 ListView 的类型(即:ListView<String>),您需要更改它以提供自定义对象。对于此示例,我们将创建一个新的 Person 类。

class Person {

    private final StringProperty name = new SimpleStringProperty();
    private final BooleanProperty important = new SimpleBooleanProperty(false);

    public Person(String name) {    
        this.name.set(name);
    }

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

    public StringProperty nameProperty() {    
        return name;
    }

    public void setName(String name) {    
        this.name.set(name);
    }

    public boolean isImportant() {    
        return important.get();
    }

    public BooleanProperty importantProperty() {    
        return important;
    }

    public void setImportant(boolean important) {    
        this.important.set(important);
    }
}

现在,您需要相应地定义您的 ListView

ListView<Person> listView = new ListView<>();

自定义 CellFactory:

CellFactoryListView 的一部分,它处理呈现 ListView 中每一行的实际内容。为了根据特定 Person 的属性更改单元格的外观,我们必须提供我们自己的实现(JavaFX 的标准实现将简单地呈现每个单元格以包含项目的 toString() 方法) .

listView.setCellFactory(cell -> new ListCell<Person>(){
    @Override
    protected void updateItem(Person person,boolean empty) {

        super.updateItem(person,empty);
            
        // First,we are only going to update the cell if there is actually an item to display there.
        if (!empty && person != null) {
                
            // Set the text of the cell to the Person's name
            setText(person.getName());

            // If the Person has the "important" flag,we can make the text bold here
            if (person.isImportant()) {
                setStyle("-fx-font-weight: bold");
            } else {
                // Remove any styles from the cell,because this Person isn't important
                setStyle(null);
            }
        } else {
            // If there is no item to display in this cell,set the text to null
            setText(null);
        }
    }
});

更新“重要”属性:

您的 MenuItem 的操作应更新所选人员的 important 属性。这相当简单:

mnuSetImportant.setOnAction(event -> {
        Person selectedPerson = listView.getSelectionModel().getSelectedItem();

        if (selectedPerson != null) {
            selectedPerson.setImportant(!selectedPerson.isImportant());
        }
    });

请注意,在这种情况下,我已将操作设置为切换此人的重要状态。您可以轻松地将属性设置为 true,但如果不添加单独的菜单选项,您将无法再次将其设置为 false

然而,在此之后,您会注意到单元格不会使用新样式更新自身。这是因为 ListView 不会“侦听”每个 Person 的属性更改。因此,在下面的示例中,我们向 extractor() 类添加了一个静态 Person 方法,该方法允许其属性触发对 ListView 的更新。


就是这样!下面是一个完整的应用程序,您可以亲自试用以查看它的实际效果:

import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;

public class ListViewItemProperties extends Application {

    public static void main(String[] args) {

        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        // **********************************************************************************************
        // Create a basic layout
        // **********************************************************************************************
        BorderPane root = new BorderPane();

        // **********************************************************************************************
        // Create the menu bar and Menu items
        // **********************************************************************************************
        MenuBar menuBar = new MenuBar();
        Menu mnuMore = new Menu("More");
        MenuItem mnuSetImportant = new MenuItem("Set important");

        // **********************************************************************************************
        // Create the ListView
        // **********************************************************************************************
        ListView<Person> listView = new ListView<>();

        // **********************************************************************************************
        // Set the action for the "Set important" menu item to update the property of the selected
        // Person in the ListView,if applicable
        // **********************************************************************************************
        mnuSetImportant.setOnAction(event -> {
            // **********************************************************************************************
            // Get reference to the currently selected Person
            // **********************************************************************************************
            Person selectedPerson = listView.getSelectionModel().getSelectedItem();

            if (selectedPerson != null) {
                // **********************************************************************************************
                // If a person has been selected,toggle their "important" property
                // **********************************************************************************************
                selectedPerson.setImportant(!selectedPerson.isImportant());
            }
        });

        // **********************************************************************************************
        // Assemble the menus
        // **********************************************************************************************
        mnuMore.getItems().add(mnuSetImportant);
        menuBar.getMenus().add(mnuMore);

        // **********************************************************************************************
        // Create some sample Persons and add them to the ListView. This will also configure the list with
        // the extractor we created in the Person class in order to trigger updates to the ListView when any 
        // of the Person's properties change.
        // **********************************************************************************************
        ObservableList<Person> people = FXCollections.observableArrayList(Person.extractor());
        people.addAll(
                new Person("Dad"),new Person("Sis"),new Person("Babe"));
        listView.setItems(people);

        // **********************************************************************************************
        // Here we will create our own CellFactory so we can set the style of the text based on the
        // important property of each Person
        // **********************************************************************************************
        listView.setCellFactory(cell -> new ListCell<Person>() {
            @Override
            protected void updateItem(Person person,boolean empty) {

                super.updateItem(person,empty);

                // First,we are only going to update the cell if there is actually an item to display there.
                if (!empty && person != null) {

                    // Set the text of the cell to the Person's name
                    setText(person.getName());

                    // If the Person has the "important" flag,we can make the text bold here
                    if (person.isImportant()) {
                        setStyle("-fx-font-weight: bold");
                    } else {
                        // Remove any styles from the cell,because this Person isn't important
                        setStyle(null);
                    }
                } else {
                    // If there is no item to display in this cell,set the text to null
                    setText(null);
                }
            }
        });

        // **********************************************************************************************
        // Assemble the Scene
        // **********************************************************************************************
        root.setTop(menuBar);
        root.setCenter(listView);

        // **********************************************************************************************
        // Set the Scene for the stage
        // **********************************************************************************************
        primaryStage.setScene(new Scene(root));

        // **********************************************************************************************
        // Configure the Stage
        // **********************************************************************************************
        primaryStage.setTitle("Test Application");
        primaryStage.show();
    }
}

class Person {

    // Name of this person
    private final StringProperty name = new SimpleStringProperty();

    // Boolean property to track whether this person has been flagged as "important"
    private final BooleanProperty important = new SimpleBooleanProperty(false);

    public Person(String name) {

        this.name.set(name);
    }

    /**
     * Callback to trigger updates whenever a property of a Person is changed. This allows our ListView
     * to refresh the cell when the "important" property changes.
     */
    public static Callback<Person,Observable[]> extractor() {

        // **********************************************************************************************
        // Return the callback which fires change events whenever either name or important properties
        // are updated. A ListView normally only listens for changes to its Items list but ignores 
        // changes to the item's internal properties.
        // **********************************************************************************************
        return (Person p) -> new Observable[]{
                p.name,p.important
        };

    }

    public String getName() {

        return name.get();
    }

    public void setName(String name) {

        this.name.set(name);
    }

    public StringProperty nameProperty() {

        return name;
    }

    public boolean isImportant() {

        return important.get();
    }

    public void setImportant(boolean important) {

        this.important.set(important);
    }

    public BooleanProperty importantProperty() {

        return important;
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?