4

Javafx 2.0 でドラッグ可能なノードを作成する方法。JavaFX は特別に GUI のみを目的としており、サンプルが必要です。

4

2 に答える 2

8

パーティーには少し遅れましたが、Node の多くのサブクラスでドラッグ可能性が必要だったので、ユーティリティ クラスを作成しました。

/**
 * Generalised implementation of 'Draggability' of a {@link Node}. The Draggable class is used as a 'namespace' for the internal
 * class/interfaces/enum.
 * @author phill
 *
 */
public class Draggable {
public enum Event {
    None, DragStart, Drag, DragEnd
}

/**
 * Marker for an entity that has draggable nature.
 * @author phill
 */
public interface Interface {
    public abstract Draggable.Nature getDraggableNature();
}

public interface Listener {
    public void accept(Nature draggableNature, Event dragEvent);
}

/**
 * Class that encapsulates the draggable nature of a node.
 * <ul>
 * <li>EventNode: the event that receives the drag events</li>
 * <li>One or more DragNodes: that move in response to the drag events. The EventNode is usually (but not always) a
 * DragNode</li>
 * <li>Listeners: listen for the drag events</li>
 * </ul>
 * @author phill
 *
 */
public static final class Nature implements EventHandler<MouseEvent> {
    private double lastMouseX = 0, lastMouseY = 0; // scene coords

    private boolean dragging = false;

    private final boolean enabled = true;
    private final Node eventNode;
    private final List<Node> dragNodes = new ArrayList<>();
    private final List<Listener> dragListeners = new ArrayList<>();

    public Nature(final Node node) {
        this(node, node);
    }

    public Nature(final Node eventNode, final Node... dragNodes) {
        this.eventNode = eventNode;
        this.dragNodes.addAll(Arrays.asList(dragNodes));
        this.eventNode.addEventHandler(MouseEvent.ANY, this);
    }

    public final boolean addDraggedNode(final Node node) {
        if (!this.dragNodes.contains(node)) {
            return this.dragNodes.add(node);
        }
        return false;
    }

    public final boolean addListener(final Listener listener) {
        return this.dragListeners.add(listener);
    }

    public final void detatch() {
        this.eventNode.removeEventFilter(MouseEvent.ANY, this);
    }

    public final List<Node> getDragNodes() {
        return new ArrayList<>(this.dragNodes);
    }

    public final Node getEventNode() {
        return this.eventNode;
    }

    @Override
    public final void handle(final MouseEvent event) {
        if (MouseEvent.MOUSE_PRESSED == event.getEventType()) {
            if (this.enabled && this.eventNode.contains(event.getX(), event.getY())) {
                this.lastMouseX = event.getSceneX();
                this.lastMouseY = event.getSceneY();
                event.consume();
            }
        } else if (MouseEvent.MOUSE_DRAGGED == event.getEventType()) {
            if (!this.dragging) {
                this.dragging = true;
                for (final Listener listener : this.dragListeners) {
                    listener.accept(this, Draggable.Event.DragStart);
                }
            }
            if (this.dragging) {
                final double deltaX = event.getSceneX() - this.lastMouseX;
                final double deltaY = event.getSceneY() - this.lastMouseY;

                for (final Node dragNode : this.dragNodes) {
                    final double initialTranslateX = dragNode.getTranslateX();
                    final double initialTranslateY = dragNode.getTranslateY();
                    dragNode.setTranslateX(initialTranslateX + deltaX);
                    dragNode.setTranslateY(initialTranslateY + deltaY);
                }

                this.lastMouseX = event.getSceneX();
                this.lastMouseY = event.getSceneY();

                event.consume();
                for (final Listener listener : this.dragListeners) {
                    listener.accept(this, Draggable.Event.Drag);
                }
            }
        } else if (MouseEvent.MOUSE_RELEASED == event.getEventType()) {
            if (this.dragging) {
                event.consume();
                this.dragging = false;
                for (final Listener listener : this.dragListeners) {
                    listener.accept(this, Draggable.Event.DragEnd);
                }
            }
        }

    }

    public final boolean removeDraggedNode(final Node node) {
        return this.dragNodes.remove(node);
    }

    public final boolean removeListener(final Listener listener) {
        return this.dragListeners.remove(listener);
    }

    /**
     * When the initial mousePressed is missing we can supply the first coordinates programmatically.
     * @param lastMouseX
     * @param lastMouseY
     */
    public final void setLastMouse(final double lastMouseX, final double lastMouseY) {
        this.lastMouseX = lastMouseX;
        this.lastMouseY = lastMouseY;
    }
}
}

これは、任意のノードに適用できます。

final Rectangle rectangle = new Rectangle(100, 100, 200, 50);
Draggable.Nature nature = new Draggable.Nature(rectangle);

そして長方形はドラッグ可能です。Draggable.Nature にリスナーを追加したり、同時にドラッグできるノードを追加したりできます。

これで私のニーズは解決しました-お役に立てば幸いです。

于 2017-10-11T20:07:51.663 に答える