2014-12-29 2 views
2

Bascially 나는 treeView에서 항목을 드래그하여 treeView의 아래쪽이나 위쪽으로 이동하면 treeView가 자동으로 아래로 스크롤되거나 쪽으로.TreeView에서 항목을 끌 때 JavaFX OnMouseDragged가 실행되지 않음

지금까지 TreeView를 확장하고 onMouseDragged 이벤트 처리기를 추가 할 수있었습니다. 이

public ExtendedTreeView() 
{ 
    super(); 

    setOnMouseDragged((MouseEvent event) -> onMouseMoved(event)); 
} 

이벤트 핸들러는 내가 드래그하고 원하는 결과를 얻을 트 리뷰에서 마우스를 이동하면

private void onMouseMoved(MouseEvent event) 
{ 
    System.out.println("onMouseMoved-----------------------------------------------------------------"); 
    System.out.println(event.getEventType().toString()); 

    // -----only apply when there is a drag event in progress 
    if(event.getEventType().equals(MouseEvent.MOUSE_DRAGGED)) 
    { 
     // -----first check if we are the scrollEdges 
     System.out.println(String.format("Size: %f : %f", getWidth(), getHeight())); 
     System.out.println(String.format("Bounds: %f : %f : %f : %f", _scrollBounds.getTop(), _scrollBounds.getRight(), _scrollBounds.getBottom(), _scrollBounds.getLeft())); 
     System.out.println(String.format("Node: %f : %f", event.getX(), event.getY())); 

     //-----up and down directions are preferred 
     ScrollDirection direction = ScrollDirection.None; 
     if(event.getY() <= _scrollBounds.getTop()) 
      direction = ScrollDirection.Top; 
     else if(event.getY() >= _scrollBounds.getBottom()) 
      direction = ScrollDirection.Bottom; 
     else if(event.getX() >= _scrollBounds.getRight()) 
      direction = ScrollDirection.Right; 
     else if(event.getX() <= _scrollBounds.getLeft()) 
      direction = ScrollDirection.Left; 

     System.out.println(String.format("Direction: %s", direction.toString())); 
    } 
} 

을 (시스템 아웃 그냥 디버그 목적으로 bascially 있습니다) 다음과 같습니다처럼.

문제는 어떻게하면 actuall 항목을 드래그하자마자 , 드래그 이벤트는 한 번만 발생하고 다시는 발생하지 않습니다.

항목에는 기본적으로 이와 같이 보이는 끌어서 놓기 조작이 있습니다. 이 컨트롤러는 실제로 그가 속한 TreeCell에 대한 정보가있는 컨트롤러입니다.

@FXML 
public void onDragDetected(MouseEvent event) 
{ 
    Base item = getTreeCell().getItem(); 

    Dragboard dragboard = getTreeCell().startDragAndDrop(TransferMode.MOVE); 

    //-----get info from the item and put it in the clipboard 

    dragboard.setContent(content); 

    //event.consume(); 
} 

@FXML 
public void onDragEntered(DragEvent event) 
{ 
    boolean acceptDrag = false; 

    Dragboard dragboard = event.getDragboard(); 

    Base current = getTreeCell().getItem(); 

    //-----get the info from the clipboard and do something with it 
    //-----essentially the acceptDrag will be set to true here 

    if((_isDragAccepted = acceptDrag)) 
    { 
     event.acceptTransferModes(TransferMode.MOVE); 
     //event.consume(); 
    } 
} 

@FXML 
public void onDragOver(DragEvent event) 
{ 
    if(_isDragAccepted) 
    { 
     event.acceptTransferModes(TransferMode.MOVE); 
     //event.consume(); 
    } 
} 

@FXML 
public void onDragExited(DragEvent event) 
{ 
    _isDragAccepted = false; 

    //event.consume(); 
} 

@SuppressWarnings("unchecked") 
@FXML 
public void onDragDropped(DragEvent event) 
{ 
    Dragboard dragboard = event.getDragboard(); 

    TreeItem<Base> currentItem = getTreeCell().getTreeItem(); 

    Base current = getTreeCell().getItem(); 

    //-----get info from clipboard again and do the necessary stuff 
    //-----essentially an item will be transfered here from one node to another 

    event.setDropCompleted(true); 

    //event.consume(); 
} 

또한 따라서이 경우, 이벤트가 다시 소스에이 이벤트가 소비되지 않은 경우, 그것은해야 거품까지 모든 방법에 따르면 this 링크

에서 자바 FX의 처리에 대한 몇 가지 정보를 가지고 TreeView도 전달해야합니까? 그래서 내가 여기서 잘못하고있는 것을 정말로 알고 싶습니다. 내가 잘못 이벤트를 수신 한

나는 문제가 무엇인지 파악 그래서 좋아

답변

4

은 내가 등록하는 데 필요한 이벤트는으로 onDragOver 이벤트 대신 onMouseDragged 사건이었다.

그래서 누군가가 이제까지 autoscrollTreeView을 필요로하는 경우에, 자동 스크롤 트 리뷰에 대한 최종 해결책은 지금과 같다 : 이것에 대한

import javafx.beans.property.DoubleProperty; 
import javafx.beans.property.LongProperty; 
import javafx.beans.property.SimpleDoubleProperty; 
import javafx.beans.property.SimpleLongProperty; 
import javafx.scene.control.TreeItem; 
import javafx.scene.control.TreeView; 
import javafx.scene.input.DragEvent; 

import com.sun.javafx.scene.control.skin.VirtualFlow; 

@SuppressWarnings("restriction") 
public class AutoscrollTreeView<T> extends TreeView<T> 
{ 
    // region Enumerations 

    private enum ScrollDirection 
    { 
     None, Top, Bottom 
    } 

    // endregion 

    // region Static 

    private static final double _milliSecondToSecondFactor = 1.0d/1000.0d; 

    // endregion 

    // region Fields 

    /** 
    * the time interval in milliseconds in which the scroll is performed 
    */ 
    private final LongProperty _checkInterval = new SimpleLongProperty(50); 
    /** 
    * the actual scroll speed when being in the scroll areas 
    */ 
    private final DoubleProperty _scrollSpeed = new SimpleDoubleProperty(1.0); 
    /** 
    * the scroll speed increment per second the user remain in the scroll area 
    */ 
    private final DoubleProperty _scrollSpeedIncrementPerSecond = new SimpleDoubleProperty(0.0); 
    /** 
    * distance from the top, which defines the area which will start a scroll in the -y axis 
    */ 
    private final DoubleProperty _dragIdentifierTop = new SimpleDoubleProperty(); 
    /** 
    * distance from the bottom, which defines the area which will start a scroll in the +y axis 
    */ 
    private final DoubleProperty _dragIdentifierBottom = new SimpleDoubleProperty(); 
    /** 
    * time at which the user entered the any scroll area 
    */ 
    private long _initialDragTime = -1; 
    /** 
    * last time the interval was checked 
    */ 
    private long _lastCheck = -1; 

    // endregion 

    // region Constructor 

    public AutoscrollTreeView() 
    { 
     super(); 

     addEventHandlers(); 
    } 

    public AutoscrollTreeView(TreeItem<T> root) 
    { 
     super(root); 

     addEventHandlers(); 
    } 

    // endregion 

    // region Getter/Setter 

    public final void setCheckInterval(long value) 
    { 
     _checkInterval.set(value); 
    } 

    public final long getCheckInterval() 
    { 
     return _checkInterval.get(); 
    } 

    public final LongProperty checkIntervalProperty() 
    { 
     return _checkInterval; 
    } 

    public final void setScrollSpeed(double value) 
    { 
     _scrollSpeed.set(value); 
    } 

    public final double getScrollSpeed() 
    { 
     return _scrollSpeed.get(); 
    } 

    public final DoubleProperty scrollSpeedProperty() 
    { 
     return _scrollSpeed; 
    } 

    public final void setScrollSpeedIncrementPerSecond(double value) 
    { 
     _scrollSpeedIncrementPerSecond.set(value); 
    } 

    public final double getScrollSpeedIncrementPerSecond() 
    { 
     return _scrollSpeedIncrementPerSecond.get(); 
    } 

    public final DoubleProperty scrollSpeedIncrementPerSecondProperty() 
    { 
     return _scrollSpeedIncrementPerSecond; 
    } 

    public final void setDragIdentiferTop(double value) 
    { 
     _dragIdentifierTop.set(value); 
    } 

    public final double getDragIdentifierTop() 
    { 
     return _dragIdentifierTop.get(); 
    } 

    public final DoubleProperty dragIdentifierTopProperty() 
    { 
     return _dragIdentifierTop; 
    } 

    public final void setDragIdentiferBottom(double value) 
    { 
     _dragIdentifierBottom.set(value); 
    } 

    public final double getDragIdentifierBottom() 
    { 
     return _dragIdentifierBottom.get(); 
    } 

    public final DoubleProperty dragIdentifierBottomProperty() 
    { 
     return _dragIdentifierBottom; 
    } 

    // endregion 

    // region Events 

    private void onDragEvent(DragEvent event) 
    { 
     // -----only apply when there is a drag event in progress 
     if(event.getEventType().equals(DragEvent.DRAG_OVER)) 
     { 
      if(_lastCheck == -1 || System.currentTimeMillis() - _lastCheck > _checkInterval.get()) 
      { 
       ScrollDirection direction = ScrollDirection.None; 
       if(event.getY() <= _dragIdentifierTop.get()) 
        direction = ScrollDirection.Top; 
       else if(event.getY() >= getHeight() - _dragIdentifierBottom.get()) 
        direction = ScrollDirection.Bottom; 

       if(direction != ScrollDirection.None) 
       { 
        double additionalScrollSpeed = 0; 
        if(_initialDragTime > 0) 
         additionalScrollSpeed = _scrollSpeedIncrementPerSecond.get() * (System.currentTimeMillis() - _initialDragTime) * _milliSecondToSecondFactor; 
        else 
         _initialDragTime = System.currentTimeMillis(); 

        if(direction == ScrollDirection.Bottom) 
         scrollY(_scrollSpeed.get() + additionalScrollSpeed); 
        else 
         scrollY(-(_scrollSpeed.get() + additionalScrollSpeed)); 
       } 
       else 
       { 
        _initialDragTime = -1; 
       } 

       _lastCheck = System.currentTimeMillis(); 
      } 
     } 
     else 
     { 
      _initialDragTime = -1; 
      _lastCheck = -1; 
     } 
    } 

    // endregion 

    // region Private 

    /** 
    * adds the necessary event filters 
    */ 
    private void addEventHandlers() 
    { 
     addEventHandler(DragEvent.DRAG_OVER, event -> onDragEvent(event)); 
     addEventHandler(DragEvent.DRAG_EXITED, event -> onDragEvent(event)); 
     addEventHandler(DragEvent.DRAG_DROPPED, event -> onDragEvent(event)); 
     addEventHandler(DragEvent.DRAG_DONE, event -> onDragEvent(event)); 
    } 

    private void scrollY(double offset) 
    { 
     VirtualFlow<?> flow = ((VirtualFlow<?>) lookup("VirtualFlow")); 
     flow.adjustPixels(offset); 
    } 

    // endregion 
} 
+0

멋진 포스트, 감사,이 문제를 해결하기 위해 노력하는 데 문제가 있었다. 그러나 if (event.getY()> = getHeight() - _dragIdentifierBottom.get())를 사용하여 약간의 버그가 발생했습니다.이 체크를 제거하고 맨 아래 스크롤을 읽지 않고 단순히 맨 위의 스크롤을 읽지 않고 단순히 else 문이 제대로 작동했습니다. 이유가 확실하지 않더라도 내 코드의 다른 곳에있을 수도 있지만 다시 한 번 감사드립니다 !! – Nathan

관련 문제