拖动Treeview中的Item时,JavaFX OnMouseDragged不会被触发

时间:2014-12-29 10:36:42

标签: java drag-and-drop treeview javafx-8

基本上我尝试实现这种行为,当从treeView拖动一个项目并且在treeView的底部或顶部时,treeView将自动向下或向上滚动。

到目前为止,我只需要扩展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()));
    }
}

当我在TreeView中拖动并移动鼠标时,它会得到所需的结果。

问题是如何 只要我拖动一个实际项目,拖动事件只会发生一次,然后再也不会再发生。

该项目还有一个拖放处理,基本上是这样的。 请注意,这实际上是一个控制器,其中包含有关他所属的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链接

获得了有关javafx中事件处理的一些信息

根据这个,如果事件没有消耗,它应该一直冒泡到源,因此如果不是它也应该传递TreeView?所以我真的想知道我在这里做错了什么。

1 个答案:

答案 0 :(得分:4)

好的所以我弄清楚问题是什么,

我正在听错事件,我需要注册的事件是onDragOver事件而不是onMouseDragged事件。

因此,如果有人需要autoscrollTreeView,autoscroll tr​​eeView的最终解决方案现在看起来像这样:

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
}