2

I have a TableView in one of the Tabs of a TabPane. I want to add a click event on the cell, user id , so that when ever the user clicks on a particular user id , i open a new tab with user specific details. how to add event listeners to all the cells in a column ?

<TableView fx:controller="tableViewController"
    fx:id="tableViewTable" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
    <columnResizePolicy>
        <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
    </columnResizePolicy>
    <columns>
        <TableColumn text="First Name">
            <cellValueFactory>
                <PropertyValueFactory property="firstName" />
            </cellValueFactory>
        </TableColumn>
        <TableColumn text="Last Name">
            <cellValueFactory>
                <PropertyValueFactory property="lastName" />
            </cellValueFactory>
        </TableColumn>
        <TableColumn text="User Id">
            <cellValueFactory>
                <PropertyValueFactory property="userId" />
            </cellValueFactory>
        </TableColumn>
    </columns>
</TableView>

This blog http://java-buddy.blogspot.com/2013/05/detect-mouse-click-on-javafx-tableview.html talks about capturing the click event programmatically, how do I do something similar when using FXML ?

user68883
  • 828
  • 1
  • 10
  • 26
  • You can't really do this in FXML; you can only get at the table cells in the cell factory. So you have to do this in the controller. (FXML is pretty much just for layout.) – James_D Feb 22 '16 at 19:48

1 Answers1

2

You need to do this in the controller. Add a fx:id to the table column (say fx:id="userIdColumn"), and then in the controller set a cell factory on the column:

public class TableViewController {

    @FXML
    private TableColumn<User, String> userIdColumn ;

    public void initialize() {
        userIdColumn.setCellFactory(tc -> {
            TableCell<User, String> cell = new TableCell<User, String>() {
                @Override
                protected void updateItem(String item, boolean empty) {
                    super.updateItem(item, empty) ;
                    setText(empty ? null : item);
                }
            };
            cell.setOnMouseClicked(e -> {
                if (! cell.isEmpty()) {
                    String userId = cell.getItem();
                    // do something with id...
                }
            };
            return cell ;
        });

        // other initialization code...
    }

    // other controller code...

}

Here I am assuming that your table displays objects of some class User that you have created, and that the user id is a String. Obviously you can adjust the types as needed.

James_D
  • 201,275
  • 16
  • 291
  • 322
  • I don't completely understand lambda expressions yet , could you please elobarate whats happeing in the setCellFactory() ? – user68883 Feb 22 '16 at 20:35
  • The cell factory is a function that maps a table column (which I called `tc` and never used) to `TableCell`s which are used to display the data in each cell in that column. So when the table view needs a table cell for that column, it calls the function you provide. – James_D Feb 22 '16 at 20:56
  • I had difficulty comprehending the lambda expression , so did it with the old way of declaring anonymus object. Now I'm able to capture the click event . But now the problem is, the User id column doesn't show the values any more ? Should I bind the UserId proprty value to the cell in the initialize method ? Earlier the following line code was binding the value . – user68883 Feb 22 '16 at 20:57
  • You still need the `cellValueFactory`, you just need the `cellFactory` in addition. – James_D Feb 22 '16 at 21:06
  • hmm.. when I add the cellFactory definition it doesn't display the values of userId anymore . I populate the list of users in initialize method – user68883 Feb 22 '16 at 21:27
  • Update your question with the code. You still have the `cellValueFactory`, and you have the `setText(...)` call in the `updateItem(...)` method? – James_D Feb 22 '16 at 21:37
  • That was it .. setText () call was missing. Thanks James – user68883 Feb 22 '16 at 21:43