java - ObservableList 中的粗体文本会破坏 ChangeListener

标签 java listview javafx observablelist

我希望 ObservableList 中有一个粗体的标题。我将其设置为粗体,但在选择它时会遇到异常 block ,因为它不是字符串。我可以将其他项目设为文本,但 ChangeListener 需要一个字符串。我只是希望异常消失。

有没有办法让它不可选或粗体且为字符串类型?

   ListView<String> list = new ListView<>();
   ObservableList items = FXCollections.observableArrayList();
   Task curr = tasklist.head;

   items.add(TextBuilder.create().text("Done Tasks").style("-fx-font-weight:bold;").build());
   items.add(curr.name + " - " + curr.description);
   //items.add(new Text(curr.name + " - " + curr.description));

   try {
        list.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<String>() {
            public void changed(ObservableValue<? extends String> ov,
                                final String oldvalue, final String newvalue) {
                if(newvalue != "Done Tasks")
                    selectedValue[0] = newvalue.split(" - ")[0];
                else
                    selectedValue[0] = "done";
            }
        });
    } catch(Exception e)
    {
        actiontarget.setFill(Color.FIREBRICK);
        actiontarget.setText("You must select a task.");
    }

最佳答案

快速而肮脏的答案

要直接回答您的愿望“我可以将其他项目设为文本,但 ChangeListener 需要一个字符串。我只是希望异常消失。”,您可以更改 ChangeListener 的类型以接受对象而不是字符串:

new ChangeListener<Object>() {
    @Override
    public void changed(ObservableValue<? extends Object> observable, Object oldValue, Object newValue) {
        if(!(newvalue instanceof Text)) {
            String string = ((String) newvalue).split(" - ")[0];
            System.out.println(string);
        }
    }
}

但是,我不推荐上述方法,因为您会失去 Java 环境提供的一些固有的类型安全优点。

编码建议

基于您的代码片段的一些建议。

  1. 使用cell factories从 ListView 的底层项目模型数据生成 ListView 单元格节点。
  2. 不要将 Text 等节点直接放入 ListView 项目列表中。 ListView项目列表用于表示不是节点的模型对象。我知道ListView javadoc没有明确说明这一点,但是,这仍然是我最好的建议。每当您认为节点适合 ListView 时,更好的选择通常是使用单元工厂。
  3. 当您放置 items 时到 ListView 中,它们应该与 ListView 的项目类型匹配(ListView 的 javadoc 确实说明了这一点)。
  4. 对于像这里这样的重要用例,请使用更复​​杂的数据结构来表示列表中的项目,以便您可以将语义数据(例如项目是否是标题)直接编码到列表中项目而不是硬编码字符串,例如“完成的任务”。
  5. 不要使用 Builder 类,例如 TextBuilder,它们已被弃用,并将从 future 的 JavaFX 运行时发行版中删除。
  6. 使用外部样式表并通过设置和取消设置样式类来操作样式,而不是在代码中内联样式定义。

合并建议示例

根据建议,您可以将问题编码为类似于下面的应用程序的代码(请注意,它仍然没有将样式信息提取到外部样式表,我将把该部分留作练习):

screenshot

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

public class ListDisplay extends Application {
    @Override
    public void start(Stage stage) {
        ListView<TaskItem> listView = new ListView<>(
                FXCollections.observableArrayList(
                        new TaskItem("Todo Tasks", null, true, true),
                        new TaskItem("Senility", "The Autumn Years", false, false),
                        new TaskItem("Death", "But I didn't eat the salmon mousse", false, false),
                        new TaskItem("Done Tasks", null, true, true),
                        new TaskItem("Birth", "The Miracle of Life", true, false),
                        new TaskItem("School", "Growth and Learning", true, false),
                        new TaskItem("Middle Age", "Stagnation", true, false),
                        new TaskItem("Live Organ Transplants", "The Machine that goes 'Ping'", true, false)
                )
        );

        listView.setCellFactory(param -> new ListCell<TaskItem>() {
            @Override
            protected void updateItem(TaskItem item, boolean empty) {
                super.updateItem(item, empty);

                if (!empty && item != null) {
                    if (item.isHeader()) {
                        setText(item.getName());
                        setStyle("-fx-font-weight: bold;");
                    } else {
                        setText(item.getName() + " - " + item.getDescription());
                        setStyle(null);
                    }
                } else {
                    setText(null);
                }
            }
        });

        listView.setPrefHeight(200);

        listView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            if (!newValue.isHeader()) {
                System.out.println("Selected: " + newValue.getName());
            }
        });

        stage.setTitle("Monty Python's Meaning of Life");
        stage.setScene(new Scene(listView));
        stage.show();
    }

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

    private static class TaskItem {
        private final String name;
        private final String description;
        private final SimpleBooleanProperty completed;
        private final boolean header;

        public TaskItem(String name, String description, boolean completed, boolean header) {
            this.name = name;
            this.description = description;
            this.completed = new SimpleBooleanProperty(completed);
            this.header = header;
        }

        public boolean isHeader() {
            return header;
        }

        public boolean isCompleted() {
            return completed.get();
        }

        public SimpleBooleanProperty completedProperty() {
            return completed;
        }

        public String getName() {
            return name;
        }

        public String getDescription() {
            return description;
        }
    }
}

关于java - ObservableList 中的粗体文本会破坏 ChangeListener,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37582535/

相关文章:

android - 如何将多个数组传递给 ListView ?

java - 如何将 Wikia 链接放入 Android 中的 ListView 中,也许 MediaWiki API 会有所帮助,但我不确定该去哪里

android - 我的 ListView 在旋转屏幕时不会保存;使用 Parcelable 接口(interface)和 onSaveInstanceState

java - 如何在Spring Boot中以Restfull方式将生成的PDF文档发送到前端?

java - JSF 2 事件列表?

java - 以编程方式解决 Bean 注入(inject)

java - 如何在 JavaFX 中将形状置于背景中?

java - 如何用单独的枚举类填充JavaFX ChoiceBox?

java - Stage.setOnCloseRequest() 和 Runtime.addShutdownHook() 有什么区别?

java - 递归如何遍历树