Reputation: 3019
Debugging for the code below, it shows that the updateItem()
method is called multiple times, but I am unable to figure out why its being called multiple times.
I wanted to add the Tooltip to the 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;
}
});
Upvotes: 0
Views: 4850
Reputation: 159341
Recommendation
I find the usability of Tooltips on ListView cells horrible, because the Tooltips intercept standard mouse events used to select rows, scroll the list, etc. So I would not recommend placing Tooltips on ListView cells.
Why multiple cells are created and updateItem is called multiple times
It is expected that a ListView have multiple cells and that updateItem() is potentially called multiple times for each cell.
A cell is created for every row in the ListView that is displayed on the scene, even if some cells are empty. A couple more cells that are offscreen are usually created for efficient scroll handling. Each time the underlying data for a ListView is initially set or modified, or the list is scrolled, updateItem() will be invoked on relevant cells to update the cell's contents. In the case of scrolling a large list, updateItem() will be invoked many, many times for each cell.
Sample code for setting a Tooltip on ListView Cells
The code below is based on the Oracle JavaFX tutorial ListView sample, but customizes it to create Tooltips for cells when you hover over them.
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);
}
}
Upvotes: 4