I'm using the TableView2 component from the library ControlsFX. In an simple example (see sourcecode below) the ArrowKey-Navigation in the table is gone after changing import javafx.scene.control.TableView to import org.controlsfx.control.tableview2.TableView2.
Done 'Research'
I read in the JavaDocs that TableView2 is a drop-in-replacement and so I'm asking what I can do to bring back the functionality of the core-component.
- The broken navigation is observable in the ControlsFX Sampler application as well.
- Maybe unrelated: There is also an
SpreadsheetViewexample which is using a different looking CellSelection-style.
Description of the problem
The example code is from the Oracle-Tutorials, I just deleted some unnecessary stuff. Try mouseclicking a table cell and press the arrow-down key. The TableSelection is not moving one row down, but the whole Focus is traversed to the TextField.

I'm using Windows 10 Pro 22H2, JDK corretto-17.0.7, JavaFX 20.0.1 and controlsfx-11.1.2
Example Code
If you change new TableView2() to new TableView() everything works as expected.
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.tableview2.TableView2;
/**
* Reduced from https://docs.oracle.com/javafx/2/ui_controls/table-view.htm.
*/
public class TableView2KeyboardNavigation extends Application
{
static class Main
{
public static void main( String[] args )
{
Application.launch( TableView2KeyboardNavigation.class, args );
}
}
private TableView<Person> table = new TableView2<>();
private final ObservableList<Person> data =
FXCollections.observableArrayList(
new Person( "Jacob", "Smith" ),
new Person( "Isabella", "Johnson" ),
new Person( "Ethan", "Williams" )
);
@Override
public void start( Stage stage )
{
final var scene = new Scene( new Group() );
stage.setTitle( "TableView2 Sample" );
final var firstNameCol = new TableColumn( "First Name" );
firstNameCol.setCellValueFactory(
new PropertyValueFactory<Person, String>( "firstName" ) );
final var lastNameCol = new TableColumn( "Last Name" );
lastNameCol.setCellValueFactory(
new PropertyValueFactory<Person, String>( "lastName" ) );
table.setItems( data );
table.getColumns().addAll( firstNameCol, lastNameCol );
final var vbox = new VBox();
vbox.getChildren().addAll( table, new TextField( "Focus lands here after ArrowDown-Key..." ) );
( (Group) scene.getRoot() ).getChildren().addAll( vbox );
stage.setScene( scene );
stage.show();
}
public static class Person
{
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private Person( String fName, String lName )
{
this.firstName = new SimpleStringProperty( fName );
this.lastName = new SimpleStringProperty( lName );
}
public String getFirstName()
{
return firstName.get();
}
public void setFirstName( String fName )
{
firstName.set( fName );
}
public String getLastName()
{
return lastName.get();
}
public void setLastName( String fName )
{
lastName.set( fName );
}
}
}
What you have observed is correct. It is indeed, that the default behaviour that is available in TableView is supressed or removed in TableView2.
The general key mapping behavior of TableView is implemented in TableViewBehaviorBase.java as below:
And this behavior implementation is set to TableView in TableViewSkin class. (Please note that it is not in TableViewSkinBase).
Now coming to TableView2 implementation, the skin of TableView2 is TableView2Skin which also extends TableViewSkinBase. But there is no behavior defined in this TableView2Skin. This is the reason why you cannot see the same behavior.
In short, TableView2 is definitely not a complete extension to TableView. Though TableView2 extends TableView, the TableView2Skin is not extending TableViewSkin. So you will not get all the features of TableView. And I am not sure whether this is an intended decision or not :).
And to get the things work as expected, it is not as easy as just adding a key handler to TableView like
tableView.setOnKeyPressed(e->...select next row...);. This will work for basic implementation. But don't expect to be as same as TableView. Because in TableVieBehavior a lot of stuff is handled to do the row selection.Below is the code that will be executed, when a key press is done in TableView.
It is up to you to take the decision of which TableView to use for your needs. If you need TableView2, then you need to somehow include the above code to your TableView2. At a basic level you can include the below one:
Below is a quick demo that demonstrates this solution on TableView2.