简体   繁体   English

JavaFX自定义ScrollBar在滚动时将事件传递给TableView

[英]JavaFX custom ScrollBar passes event to TableView on scrolling

The situation : I have a very big table in DB (let's suppose 100000000000). 情况 :我在DB中有一个非常大的表(让我们假设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. 我需要在此表中显示tableview中的项目,但当然不是全部,而只需要用户需要查看的项目。 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. 例如,他对id为500000的项目感兴趣。我在tableview中显示这个项目+之前的10个项目和项目之后的+10个项目,ID为500000.如果他需要查看更多项目,那么在桌面视图上滚动鼠标滚轮,或者向上向下键,他使程序从数据库表中动态加载项目,并在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. 我的解决方案 :为了向他展示他在滚动条上的真实位置(根据DB中的所有行),我在StackPane中创建了假滚动条并将其放在tableview滚动条上方。 It was the only solution I could find because tableview scrollbar values are calculated automatically upon items in tableview. 这是我能找到的唯一解决方案,因为tableview滚动条值是自动计算在tableview中的项目。

The only problem is that user can scroll mouse wheel not above tableview (this case everything is ok), but above this fake scrollbar. 唯一的问题是用户可以滚动鼠标滚轮而不是在tableview上方(这种情况一切正常),但在这个假滚动条上方。 In order to avoid difficult calculations I want only to pass scrolling events from this fake scrollbar to tableview. 为了避免困难的计算,我只想将滚动事件从这个假滚动条传递到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. 换句话说,我希望当用户在我的滚动条上滚动鼠标滚轮时,tableview的行为就像用户在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? 怎么做?

If I'm not mistaken you're trying to bind value of TableView 's inner scrollbar to value of your custom ScrollBar . 如果我没弄错的话,你试图将TableView的内部滚动条的值绑定到自定义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. 获取TableView滚动条的功劳是从这篇文章转到@James_D。


Remarks: 备注:

I don't know why you're using a ScrollBar and trying to manually set TableView 's inner scroll bar's value. 我不知道你为什么使用ScrollBar并试图手动设置TableView的内部滚动条的值。 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. 这似乎不是一个好习惯,因为我们被迫使用可能会发生变化的非公共API。 Maybe it's a good idea to consider using public methods like TableView#scrollTo(int index) or similar methods. 也许考虑使用TableView#scrollTo(int index)或类似方法之类的公共方法是个好主意。

Firing the event on the ScrollBar of the TableView should do the trick. 在TableView的ScrollBar上触发事件应该可以解决问题。 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);
            }
        });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM