Reputation: 149
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
Reputation: 623
Your first problem is that your VBox
is not scaling correctly with the scene, which means that your ScrollPane
s 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 ScrollPane
s scale properly with your scene. However, you still need to bind their vvalue
s so that they match vertically. Add this line below where you bind their hvalue
s:
sp.hvalueProperty().bindBidirectional(sp2.hvalueProperty());
sp.vvalueProperty().bindBidirectional(sp2.vvalueProperty()); //Add this line
Now your scrolling works properly:
Upvotes: 1
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