Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a tooltip to a TableView header cell in JavaFX 8

Does anyone know how to add a tooltip to a column header in a TableView ?

There are many places where are explained how to add the tooltip to data cells, but I didn't find a way to add the tooltip to header.

Using the tool ScenicView, I can see that the headers are Labels inside a TableColumnHeader object, but It seems that It is not a public object.

Any suggestions ?

like image 906
Roberto Avatar asked Apr 22 '14 16:04

Roberto


3 Answers

    TableColumn<Person, String> firstNameCol = new TableColumn<>();
    Label firstNameLabel = new Label("First Name");
    firstNameLabel.setTooltip(new Tooltip("This column shows the first name"));
    firstNameCol.setGraphic(firstNameLabel);
like image 101
James_D Avatar answered Nov 12 '22 08:11

James_D


This is an extended answer to James_D. (I don't have the reputation to comment):

To make the label connect with textProperty of the column and just hide the original text, so it does not mess up the rest of the table functionality:

nameLabel.textProperty().bindBidirectional(textProperty());
nameLabel.getStyleClass().add("column-header-label");
nameLabel.setMaxWidth(Double.MAX_VALUE); //Makes it take up the full width of the table column header and tooltip is shown more easily.

css:

.table-view .column-header .label{
    -fx-content-display: graphic-only;
}
.table-view .column-header .label .column-header-label{
    -fx-content-display: text-only;
}
like image 10
Jesper Pedersen Avatar answered Nov 12 '22 08:11

Jesper Pedersen


The solution

Alternatively, you can look up the label that's already there and just give it a tool tip.

In order to .lookup() an element the table needs to be rendered already. To be sure that your code runs after the table is rendered, just wrap your code in a Platform.runlater().

// We need to do this after the table has been rendered (we can't look up elements until then)
Platform.runLater(() -> {
    // Prepare a tooltip
    Tooltip tooltip = new Tooltip("This is a super cool control; here's how to work it...");
    tooltip.setWrapText(true);
    tooltip.setMaxWidth(200);

    // Get column's column header
    TableColumnHeader header = (TableColumnHeader) historyTable.lookup("#" + column.getId());

    // Get column header's (untooltipped) label
    Label label = (Label) header.lookup(".label");

    // Give the label a tooltip
    label.setTooltip(tooltip);

    // Makes the tooltip display, no matter where the mouse is inside the column header.
    label.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
}

The solution at scale

If you want to do this for your whole set of columns, you might put them all in a LinkedHashMap (this will just help you organizationally by keeping your columns associated with their messages):

// We'll use this to associate columns with messages for right now.
LinkedHashMap<TableColumn<Person, String>, String> tableColumns = new LinkedHashMap<>();

// Each column gets a helpful message
tableColumns.put(numberOfBoxesColumn, "The total number of boxes that have arrived");
tableColumns.put(backordersColumn, "Use these columns as a measure of how urgently the Purchase Order needs to be processed.");
/*... put each column in along with it's message */

... then use a for-each loop to loop through and give each column a tooltip ...

// Make a tooltip out of each message. Give each column('s label) it's tooltip.
for (Map.Entry<TableColumn<Person, String>, String> pair : tableColumns.entrySet()) {
    
    TableColumn<Person, String> column;
    String message;

    // Get the column and message
    column = pair.getKey();
    message = pair.getValue();

    // Prepare a tooltip
    Tooltip tooltip = new Tooltip(message);
    tooltip.setWrapText(true);
    tooltip.setMaxWidth(200);

    // Get column's column header
    TableColumnHeader header = (TableColumnHeader) historyTable.lookup("#" + column.getId());

    // Get column header's (untooltipped) label
    Label label = (Label) header.lookup(".label");

    // Give the label a tooltip
    label.setTooltip(tooltip);

    // Makes the tooltip display, no matter where the mouse is inside the column header.
    label.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
}

NOTE: I tried the combination of Jesper and James' solutions before coming up with this one. Sadly, when I did, the CSS caused all of my labels to disappear when I look at my .fxml layout in SceneBuilder. And we just can't have that, can we? (okay maybe I just couldn't have that).

Where're mah labels!

like image 5
Brad Turek Avatar answered Nov 12 '22 10:11

Brad Turek