0

调试下面的代码,它显示该updateItem()方法被多次调用,但我无法弄清楚为什么它被多次调用。

我想将工具提示添加到 ListView。

// THIS TO ADD TOOLTIP, NOT WORKING FULLY.
lstComments.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
    @Override
    public ListCell<String> call(ListView<String> p) {
        final Tooltip tt = new Tooltip();
        final ListCell<String> cell = new ListCell<String>() {
            String message = ca.getMessage();

            @Override
            public void updateItem(String s, boolean empty) {
                super.updateItem(s, empty);
                tt.setText(message);
                setTooltip(tt);
            }
        };

        cell.setText(ca.getMessage());
        return cell;
    }
});
4

1 回答 1

4

推荐

我发现 ListView 单元格上的 Tooltips 的可用性很糟糕,因为 Tooltips 拦截用于选择行、滚动列表等的标准鼠标事件。所以我不建议将 Tooltips 放在 ListView 单元格上。

为什么会创建多个单元格并多次调用 updateItem

预计 ListView 有多个单元格,并且可能会为每个单元格多次调用updateItem() 。

即使某些单元格是空的,也会为场景中显示的 ListView 中的每一行创建一个单元格。通常会创建更多屏幕外的单元格以进行有效的滚动处理。每次初始设置或修改 ListView 的基础数据或滚动列表时,都会在相关单元格上调用 updateItem() 以更新单元格的内容。在滚动大列表的情况下,updateItem() 将为每个单元格调用很多次。

在 ListView 单元格上设置工具提示的示例代码

下面的代码基于Oracle JavaFX 教程 ListView 示例,但对其进行了自定义,以便在将鼠标悬停在单元格上时为单元格创建工具提示。

mport javafx.application.Application;
import javafx.collections.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;

public class ListViewSample extends Application {

    ListView<String> list = new ListView<String>();
    ObservableList<String> data = FXCollections.observableArrayList(
            "chocolate", "salmon", "gold", "coral", "darkorchid",
            "darkgoldenrod", "lightsalmon", "black", "rosybrown", "blue",
            "blueviolet", "brown");
    final Label label = new Label();

    @Override
    public void start(Stage stage) {
        VBox box = new VBox();
        Scene scene = new Scene(box, 200, 200);
        stage.setScene(scene);
        stage.setTitle("ListViewSample");
        box.getChildren().addAll(list, label);
        VBox.setVgrow(list, Priority.ALWAYS);

        label.setLayoutX(10);
        label.setLayoutY(115);
        label.setFont(Font.font("Verdana", 20));

        list.setItems(data);

        list.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
            @Override public ListCell<String> call(ListView<String> list) {
                return new ColorRectCell();
            }
        });

        list.getSelectionModel().selectedItemProperty().addListener(
                (ov, old_val, new_val) -> {
                        label.setText(new_val);
                        label.setTextFill(Color.web(new_val));
                });
        stage.show();
    }

    static class ColorRectCell extends ListCell<String> {
        final Rectangle swatch = new Rectangle(30, 30);
        final Tooltip tip = new Tooltip();

        public ColorRectCell() {
            tip.setGraphic(swatch);
        }

        @Override
        public void updateItem(String color, boolean empty) {
            super.updateItem(color, empty);

            if (color != null) {
                swatch.setFill(Color.valueOf(color.toUpperCase()));
                setText(color);
                setTooltip(tip);
            } else {
                setText("");
                setTooltip(null);
            }
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}
于 2013-08-10T07:20:21.750 回答