Это немного похоже на взлом, но вы можете получить дочерний узел Text
в ячейке, выполнив поиск в графе сцены под ячейкой после выполнения макета, а затем создать привязку для всплывающей подсказки, которая проверяет, есть ли у ячейки текст такой же, как и текст текста. Обратите внимание, что мы игнорируем любые графы c, установленные для ячейки здесь, поэтому выполняется поиск только узла Text, отображающего свойство text
ячейки:
setCellFactory(tc -> new TableCell<>() {
private Text text ;
private Tooltip tooltip = new Tooltip() ;
{
tooltip.textProperty().bind(textProperty());
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText("");
} else {
setText(item);
}
}
@Override
protected void layoutChildren() {
super.layoutChildren();
if (text == null) {
text = findTextNode(this);
bindTooltip();
}
}
private void bindTooltip() {
tooltipProperty().bind(Bindings.createObjectBinding(() -> {
if (getItem()==null) return null ;
if (getText().equals(text.getText())) return null ;
return tooltip ;
}, text.textProperty(), itemProperty(), textProperty()));
}
// recursively search through child node graph to find the Text node
private Text findTextNode(Node root) {
// Ignore the graphic and all its child nodes:
if (root == getGraphic()) {
return null ;
}
if (root instanceof Text) {
return (Text) root ;
}
if (root instanceof Parent) {
for (Node node : ((Parent)root).getChildrenUnmodifiable()) {
Text text = findTextNode(node);
if (text != null) return text ;
}
}
return null ;
}
});
Вот полный рабочий пример:
import java.util.Random;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.BorderPane;
import javafx.scene.text.Text;
import javafx.stage.Stage;
/**
* JavaFX App
*/
public class App extends Application {
@Override
public void start(Stage stage) {
var table = new TableView<Item>();
var itemCol = column("Item", Item::nameProperty);
var valueCol = column("Value", Item::valueProperty);
table.getColumns().add(itemCol);
table.getColumns().add(valueCol);
itemCol.setCellFactory(tc -> new TableCell<>() {
private Text text ;
private Tooltip tooltip = new Tooltip() ;
{
tooltip.textProperty().bind(textProperty());
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText("");
} else {
setText(item);
}
}
@Override
protected void layoutChildren() {
super.layoutChildren();
if (text == null) {
text = findTextNode(this);
bindTooltip();
}
}
private void bindTooltip() {
tooltipProperty().bind(Bindings.createObjectBinding(() -> {
if (getItem()==null) return null ;
if (getText().equals(text.getText())) return null ;
return tooltip ;
}, text.textProperty(), itemProperty(), textProperty()));
}
// recursively search through child node graph to find the Text node
private Text findTextNode(Node root) {
// Ignore the graphic and all its child nodes:
if (root == getGraphic()) {
return null ;
}
if (root instanceof Text) {
return (Text) root ;
}
if (root instanceof Parent) {
for (Node node : ((Parent)root).getChildrenUnmodifiable()) {
Text text = findTextNode(node);
if (text != null) return text ;
}
}
return null ;
}
});
var rng = new Random();
for (int i = 1 ; i <= 40 ; i++) {
table.getItems().add(new Item("Item "+i, rng.nextInt(100)));
}
var scene = new Scene(new BorderPane(table));
stage.setScene(scene);
stage.show();
}
public static <S,T> TableColumn<S,T> column(String title, Function<S, Property<T>> prop) {
TableColumn<S,T> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> prop.apply(cellData.getValue()));
return col ;
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty value = new SimpleIntegerProperty();
public Item(String name, int value) {
this.name.set(name);
this.value.set(value);
}
public final StringProperty nameProperty() {
return name ;
}
public final IntegerProperty valueProperty() {
return value ;
}
}
public static void main(String[] args) {
launch();
}
}