user5182503
user5182503

Reputation:

JavaFX custom ScrollBar passes event to TableView on scrolling

The situation: I have a very big table in DB (let's suppose 100000000000). And I need to show items in tableview from this table but of course not all, but only those which user needs to see. For example he is interested in item with id 500000. I show him this item in tableview + 10 items before and +10 items after item with id 500000. If he needs to see more, then by scrolling mouse wheel on tableview, or up and down keys he makes program dynamically load items from database table and insert items before (on moving up) or after (on moving down) items in tableview.

My solution:In order to show him his real position on scrollbar (according to all rows in DB), I created fake scrollbar in StackPane and put it above tableview scrollbar. It was the only solution I could find because tableview scrollbar values are calculated automatically upon items in tableview.

The only problem is that user can scroll mouse wheel not above tableview (this case everything is ok), but above this fake scrollbar. In order to avoid difficult calculations I want only to pass scrolling events from this fake scrollbar to tableview. By other words I want that when user is scrolling mouse wheel on my scrollbar, the tableview behave like the user is scrolling mouse wheel on tableview. This is my code

ScrollBar scrollBar=new ScrollBar;
TableView tableView=new TableView();
...
scrollBar.addEventFilter(ScrollEvent.ANY, new EventHandler<ScrollEvent>() {
   @Override
   public void handle(ScrollEvent scrollEvent) {
   //we throwing this event to tableview
   tableView.fireEvent(scrollEvent);
   }
});

However it does not work. How to do it?

Upvotes: 4

Views: 1411

Answers (2)

Matthias
Matthias

Reputation: 1005

Firing the event on the ScrollBar of the TableView should do the trick. Moreover, I would consume the original event and fire a retargetted event as follows:

        scrollBar.addEventFilter(ScrollEvent.SCROLL, new EventHandler<ScrollEvent>() {
            @Override
            public void handle(ScrollEvent event) {
                event.consume();
                Node target = tableScrollBar;
                ScrollEvent retargettedScrollEvent = new ScrollEvent(target, target, event.getEventType(),
                        event.getX(), event.getY(), event.getScreenX(), event.getScreenY(), event.isShiftDown(),
                        event.isControlDown(), event.isAltDown(), event.isMetaDown(), event.isDirect(),
                        event.isInertia(), event.getDeltaX(), event.getDeltaY(), event.getTotalDeltaX(),
                        event.getTotalDeltaY(), event.getTextDeltaXUnits(), event.getTextDeltaX(),
                        event.getTextDeltaYUnits(), event.getTextDeltaY(), event.getTouchCount(),
                        event.getPickResult());
                Event.fireEvent(target, retargettedScrollEvent);
            }
        });

Upvotes: 1

Omid
Omid

Reputation: 6103

If I'm not mistaken you're trying to bind value of TableView's inner scrollbar to value of your custom ScrollBar.

If you want this behavior to be triggered only by scrolling using mouse wheel use:

scrollBar.addEventFilter(ScrollEvent.SCROLL, new EventHandler<ScrollEvent>() {
    @Override
    public void handle(ScrollEvent event) {
        ScrollBar tableViewScrolllBar = (ScrollBar) tableView.lookup(".scroll-bar:vertical");
        tableViewScrolllBar.setValue(scrollBar.getValue() / scrollBar.getMax());
    }
});

If you want this behavior to be triggered by scrolling both by mouse wheel and mouse click use:

scrollBar.valueProperty().addListener(new ChangeListener<Number>() {
    @Override
    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
        ScrollBar tableViewScrolllBar = (ScrollBar) tableView.lookup(".scroll-bar:vertical");
        tableViewScrolllBar.setValue(scrollBar.getValue() / scrollBar.getMax());
    }
});

The credit for obtaining the TableView's scroll bar goes to @James_D from this post.


Remarks:

I don't know why you're using a ScrollBar and trying to manually set TableView's inner scroll bar's value. It doesn't seem to be a good practice since we are forced to use the non public API which may be subject to change. Maybe it's a good idea to consider using public methods like TableView#scrollTo(int index) or similar methods.

Upvotes: 1

Related Questions