Search code examples
javajavafxjavafx-2javafx-8

Adding hover listener to cells of a specific column in javafx table


I want to create a OnMouseOver Listener to cells of a specific column of a TableView, such that a popup window should appeared with some message, when I hover to it's cells. This is how I am creating a table and its columns.

private TableView<Stock> stockTable = new TableView<>();
ObservableList columns = stockTable.getColumns();
public TableColumn createTextColumn(String columnName, String columnCaption,BooleanProperty editingStarted) {
    TableColumn column = new TableColumn(columnCaption);
    column.setCellValueFactory(new PropertyValueFactory<>(columnName));
    column.setCellFactory(TextFieldTableCell.forTableColumn());
    return column;
}
final TableColumn nameColumn 
                         = createTextColumn("name", "Product Name", editingStarted);
columns.add(nameColumn);

So is it possible to do it. I know how to create listeners for rows. But I found nothing on internet on listening to cells of table. Thanks in advance for any help.


Solution

  • You already used the TextFieldTableCell.forTableColumn() which you need to rewrite to suit your needs

    import javafx.event.EventHandler;
    import javafx.scene.control.Label;
    import javafx.scene.control.TableCell;
    import javafx.scene.control.TableColumn;
    import javafx.scene.control.cell.TextFieldTableCell;
    import javafx.scene.input.MouseEvent;
    import javafx.stage.Popup;
    import javafx.util.Callback;
    import javafx.util.StringConverter;
    import javafx.util.converter.DefaultStringConverter;
    
    public final class CustomTextFieldTableCell<S, T> extends TextFieldTableCell<S, T> {
    
        public static <S> Callback<TableColumn<S, String>, TableCell<S, String>> forTableColumn() {
            return forTableColumn(new DefaultStringConverter());
        }
    
        public static <S, T> Callback<TableColumn<S, T>, TableCell<S, T>> forTableColumn(final StringConverter<T> converter) {
            return new Callback<TableColumn<S, T>, TableCell<S, T>>() {
                @Override
                public TableCell<S, T> call(TableColumn<S, T> list) {
                    final TextFieldTableCell<S, T> result = new TextFieldTableCell<S, T>(converter);
                    final Popup popup = new Popup();
                    popup.setAutoHide(true);
    
                    final EventHandler<MouseEvent> hoverListener = new EventHandler<MouseEvent>() {
    
                        @Override
                        public void handle(MouseEvent event) {
                            final Label popupContent = new Label("this is a popup showing the content = '" + result.getText() + "'");
                            popupContent.setStyle("-fx-background-color: #64b5f6; -fx-border-color: #000000; -fx-border-width: 1px; -fx-padding: 5px; -fx-text-fill: white;");
    
                            popup.getContent().clear();
                            popup.getContent().addAll(popupContent);
    
                            if (event.getEventType() == MouseEvent.MOUSE_EXITED) {
                                popup.hide();
                            } else if (event.getEventType() == MouseEvent.MOUSE_ENTERED) {
                                popup.show(result, event.getScreenX() + 10, event.getScreenY());                
                            }
                        }
                    };
    
                    result.setOnMouseEntered(hoverListener);
                    result.setOnMouseExited(hoverListener);
                    return result;
                }
            };
        }
    }
    

    To use it you need to change your code to

    column.setCellFactory(CustomTextFieldTableCell.forTableColumn());
    

    The result looks like this

    enter image description here