生活随笔
收集整理的這篇文章主要介紹了
JavaFX技巧15:ListView自动滚动
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
我最近不得不為FlexGanttFX實現自動滾動功能,并認為我的解決方案可能對其他人有用。 您可以在下面的清單中找到它的基本概念。 主要思想是使用后臺線程來調整列表視圖使用的虛擬流節點的像素位置。 當檢測到“靠近”頂部或底部邊緣的拖拉時,線程開始。 “接近”由接近變量定義。
通過為接近值使用屬性以及為線程化工作使用類型“任務”和“服務”,顯然可以改進此代碼。
package com.dlsc;import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.control.ListView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.Region;/** Yes, unfortunately we need to use private API for this.*/
import com.sun.javafx.scene.control.skin.VirtualFlow;public class AutoscrollListView<T> extends ListView<T> {final double proximity = 20;public AutoscrollListView() {addEventFilter(MouseEvent.DRAG_DETECTED,evt -> startDrag());addEventFilter(DragEvent.DRAG_OVER,evt -> autoscrollIfNeeded(evt));addEventFilter(DragEvent.DRAG_EXITED,evt -> stopAutoScrollIfNeeded(evt));addEventFilter(DragEvent.DRAG_DROPPED,evt -> stopAutoScrollIfNeeded(evt));addEventFilter(DragEvent.DRAG_DONE,evt -> stopAutoScrollIfNeeded(evt));}private void startDrag() {Dragboard db = startDragAndDrop(TransferMode.MOVE);ClipboardContent content = new ClipboardContent();/** We have to add some content, otherwise drag over* will not be called.*/content.putString("dummy");db.setContent(content);}private void autoscrollIfNeeded(DragEvent evt) {evt.acceptTransferModes(TransferMode.ANY);/** Determine the "hot" region that will trigger automatic scrolling.* Ideally we use the clipped container of the list view skin but when* the rows are empty the dimensions of the clipped container will be* 0x0. In this case we try to use the virtual flow.*/Region hotRegion = getClippedContainer();if (hotRegion.getBoundsInLocal().getWidth() < 1) {hotRegion = this;if (hotRegion.getBoundsInLocal().getWidth() < 1) {stopAutoScrollIfNeeded(evt);return;}}double yOffset = 0;// y offsetdouble delta = evt.getSceneY() -hotRegion.localToScene(0, 0).getY();if (delta < proximity) {yOffset = -(proximity - delta);}delta = hotRegion.localToScene(0, 0).getY() +hotRegion.getHeight() -evt.getSceneY();if (delta < proximity) {yOffset = proximity - delta;}if (yOffset != 0) {autoscroll(yOffset);} else {stopAutoScrollIfNeeded(evt);}}private VirtualFlow<?> getVirtualFlow() {return (VirtualFlow<?>) lookup("VirtualFlow");}private Region getClippedContainer() {/** Safest way to find the clipped container. lookup() does not work at* all.*/for (Node child :getVirtualFlow().getChildrenUnmodifiable()) {if (child.getStyleClass().contains("clipped-container")) {return (Region) child;}}return null;}class ScrollThread extends Thread {private boolean running = true;private double yOffset;public ScrollThread() {super("Autoscrolling List View");setDaemon(true);}@Overridepublic void run() {/** Some initial delay, especially useful when* dragging something in from the outside.*/try {Thread.sleep(300);} catch (InterruptedException e1) {e1.printStackTrace();}while (running) {Platform.runLater(() -> {scrollY();});try {sleep(15);} catch (InterruptedException e) {e.printStackTrace();}}}private void scrollY() {VirtualFlow<?> flow = getVirtualFlow();flow.adjustPixels(yOffset);}public void stopRunning() {this.running = false;}public void setDelta(double yOffset) {this.yOffset = yOffset;}}private ScrollThread scrollThread;private void autoscroll(double yOffset) {if (scrollThread == null) {scrollThread = new ScrollThread();scrollThread.start();}scrollThread.setDelta(yOffset);}private void stopAutoScrollIfNeeded(DragEvent evt) {if (scrollThread != null) {scrollThread.stopRunning();scrollThread = null;}}
}
翻譯自: https://www.javacodegeeks.com/2014/11/javafx-tip-15-listview-autoscrolling.html
總結
以上是生活随笔為你收集整理的JavaFX技巧15:ListView自动滚动的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。