Matt
Matt

Reputation: 149

JavaFX TableView: remove/disable scollbars from the table(using a ScrollPane instead)

I have two tables, of which I would like to connect the scrollbars, so they can be scrolled simultaneously. As far as I know the binding of the TableViews own scrollbars is not possible(correct me if I´m wrong), so i decided to wrap each TableView in a ScrollPane.

However the scrolling of the table is still set to the TableView own scrollbars.

Beneath is a basic code example. As you can see, the bidirectional binding of the ScrollPane scrollbars works. However the data in the table is uneffected by this, due to the problem I described above(main control is TableViews own Scrollbar).

Can someone help me out on this? I would like to move through the TableView with the ScrollPane scrollbars, instead of using TableViews scrollbars(since I can´t bind them).

public class Main extends Application {
    private TableView<Person> table = new TableView<>();
    private TableView<Person> table2 = new TableView<>();
    private final ObservableList<Person> data =
            FXCollections.observableArrayList(
                    new Person("Jacob", "Smith"),
                    new Person("Isabella", "Johnson"),
                    new Person("Ethan", "Williams"),
                    new Person("Emma", "Jones"),
                    new Person("Michael", "Brown")
            );

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View Sample");
        stage.setWidth(300);
        stage.setHeight(1000);

        TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
        firstNameCol.setPrefWidth(100);
        firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));

        TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
        lastNameCol.setPrefWidth(100);
        lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));

        table.setItems(data);
        table.getColumns().addAll(firstNameCol, lastNameCol);

        table2.setItems(data);
        table2.getColumns().addAll(firstNameCol, lastNameCol);

        ScrollPane sp = new ScrollPane(table);
        sp.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
        sp.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);

        ScrollPane sp2 = new ScrollPane(table2);
        sp2.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
        sp2.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);

        sp.setHmax(3);
        sp2.setHmax(3);
        sp.hvalueProperty().bindBidirectional(sp2.hvalueProperty());

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().addAll(sp, sp2);

        ((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);
        }
    }
}

Upvotes: 0

Views: 596

Answers (2)

InternetUnexplorer
InternetUnexplorer

Reputation: 623

Your first problem is that your VBox is not scaling correctly with the scene, which means that your ScrollPanes will never be smaller than their content. You can fix this by changing this:

((Group) scene.getRoot()).getChildren().addAll(vbox);

to this:

Scene scene = new Scene(vbox);

You will also have to remove your previous declaration at the beginning of start:

Scene scene = new Scene(new Group()); //Remove this line

Now your ScrollPanes scale properly with your scene. However, you still need to bind their vvalues so that they match vertically. Add this line below where you bind their hvalues:

sp.hvalueProperty().bindBidirectional(sp2.hvalueProperty());
sp.vvalueProperty().bindBidirectional(sp2.vvalueProperty()); //Add this line

Now your scrolling works properly:

working scrollbars

Upvotes: 1

Sunflame
Sunflame

Reputation: 3186

it is possible to bind the scrollbars this way :

void bindScrollBars(TableView<?> firstTable, TableView<?> secondTable, Orienatation orieantation){
    ScrollBar firstScrollBar = null;
    ScrollBar secondScrollBar = null;

    for (Node node : firstTable.lookupAll(".scroll-bar")) {
            if (node instanceof ScrollBar && ((ScrollBar) node).getOrientation().equals(orientation)) {
                firstScrollBar= (ScrollBar) node;
            }
    }

    for (Node node : secondTable.lookupAll(".scroll-bar")) {
            if (node instanceof ScrollBar && ((ScrollBar) node).getOrientation().equals(orientation)) {
               secondScrollBar = (ScrollBar) node;
            }
     }

    if(firstScrollBar != null && secondScrollBar != null) { firstScrollBar.valueProperty().bindBidirectional(secondScrollBar.valueProperty()); }

For me it works fine, and you can bind it both horizontally and vertically.

Upvotes: 1

Related Questions