如何设置Menubutton总是在其他组件之上,如HBox(可拖动)

时间:2015-06-03 05:03:59

标签: javafx

我有一个父母VBox,它有一个菜单按钮和一个可拖动的HBox。当我拖动HBox时,菜单按钮没有响应(因为HBox设置在菜单按钮上)。如果可以拖动,我如何在HBox顶部设置菜单按钮?

HBoxandVBoxExampleupdated.java:

import DraggableNode;
import javafx.scene.chart.NumberAxis;

import javafx.application.Application;
import javafx.geometry.Insets;

import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.Label;
import javafx.scene.control.MenuButton;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.BorderWidths;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class HBoxandVBoxExampleupdated extends Application
{
    static Pane             pane    = new Pane();
    static DraggableNode    node    = new DraggableNode();
    static NumberAxis       noaxis  = new NumberAxis();
    static String           ref     = "HHHHHelllelelelellelellelelellelelelaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

    static HBox             nobox   = new HBox();
    static NumberAxis       lineXAxis;
    static String           Style   = "-fx-border-color: blue;\n"
                                            + "-fx-border-insets: 5;\n"
                                            + "-fx-border-width: 3;\n"
                                            + "-fx-border-style: dashed;\n";
    static String           Style1  = "-fx-border-color: red;\n"
                                            + "-fx-border-insets: 5;\n"
                                            + "-fx-border-width: 3;\n"
                                            + "-fx-border-style: dashed;\n";

    @Override
    public void start(Stage primaryStage) throws Exception
    {
        pane.setStyle(Style);
        node.setStyle(Style1);
        VBox mainbox = new VBox(80);
        mainbox.setAlignment(Pos.CENTER);
        mainbox.setPadding(new Insets(50, 30, 100, 50));

        VBox hbox = new VBox(60);
        hbox.setAlignment(Pos.CENTER); // default TOP_LEFT
        HBox vbox1 = new HBox();
        HBox vbox2 = new HBox(10);
        HBox vbox3 = new HBox(20);

        Button close = new Button("X");
        Button close1 = new Button("X");
        MenuButton vcfmenu = new MenuButton("Vcf");

        vcfmenu.getItems().add(new CheckMenuItem("About This Track"));
        vcfmenu.getItems().add(new CheckMenuItem("Ping To Tap"));
        vcfmenu.getItems().add(new CheckMenuItem("Edit Config"));
        vcfmenu.getItems().add(new CheckMenuItem("Delete Track"));
        vcfmenu.getItems().add(new CheckMenuItem("Save Track Data"));
        vcfmenu.getItems().add(new CheckMenuItem("Show Labels"));
        vcfmenu.getItems().add(new CheckMenuItem("Hides Sites Passing All Filters"));
        vcfmenu.getItems().add(new CheckMenuItem("Hides Sites not Passing All Filters"));

        vbox2.getChildren().add(vcfmenu);

        for (String s : ref.split("")) {
            Label l = new Label(s);
            l.setBorder(new Border(
                    new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT)));
            l.setBackground(
                    new Background(
                            new BackgroundFill(
                                    (s.equals("N") ? Color.web("#DDDDDD")
                                            : (s.equals("A") ? Color.web("#00BF00")
                                                    : (s.equals("C") ? Color.web("#0099FF")
                                                            : (s.equals("T") ? Color.web("#F00")
                                                                    : Color.web("#D5BB04"))))),
                                    CornerRadii.EMPTY, Insets.EMPTY)));
            l.setAlignment(Pos.CENTER);
            l.setPadding(new Insets(1, 4, 1, 4));

            vbox1.getChildren().add(l);

        }

        lineXAxis = new NumberAxis(1, ref.length(), 4);

        nobox.getChildren().add(lineXAxis);
        nobox.setHgrow(lineXAxis, Priority.ALWAYS);

        mainbox.getChildren().addAll(vbox2);
        hbox.getChildren().addAll(nobox, vbox1);

        node.getChildren().add(hbox);
        pane.getChildren().addAll(node, mainbox);
        Scene scene = new Scene(pane, 1150, 250);

        primaryStage.setTitle("HBox and VBox Example");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args)
    {
        Application.launch(args);
    }
}

DraggableNode.java:

import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;

public class DraggableNode extends StackPane {

    private double  x           = 0;
    private double  y           = 0;

    private double  mousex      = 0;
    private double  mousey      = 0;
    private Node    view;
    private boolean dragging    = false;
    private boolean moveToFront = true;
    private double  size        = 0;
    private double  newSize     = 0;

    public DraggableNode() {
        init();
    }

    public DraggableNode(Node view) {
        this.view = view;

        getChildren().add(view);
        setMouseTransparent(true);
        init();
    }

    private void init() {

        onMousePressedProperty().set(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                getScene().setCursor(Cursor.HAND);

                // record the current mouse X and Y position on Node
                mousex = event.getSceneX();
                mousey = event.getSceneY();

                x = getLayoutX();
                y = getLayoutY();

                if (isMoveToFront()) {
                    toFront();
                }
            }
        });

        onMouseDraggedProperty().set(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {

                double offsetX = event.getSceneX() - mousex;

                x += offsetX;

                double scaledX = x;
                System.out.println(" : " + scaledX);
                if (scaledX > 0)
                {
                    return;
                }

                setLayoutX(scaledX);

                dragging = false;
                mousex = event.getSceneX();

                event.consume();
            }
        });

        onMouseClickedProperty().set(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {

                dragging = false;
            }
        });

    }

    /**
     * @return the dragging
     */
    protected boolean isDragging() {
        return dragging;
    }

    /**
     * @return the view
     */
    public Node getView() {
        return view;
    }

    /**
     * @param moveToFront
     *            the moveToFront to set
     */
    public void setMoveToFront(boolean moveToFront) {
        this.moveToFront = moveToFront;
    }

    /**
     * @return the moveToFront
     */
    public boolean isMoveToFront() {
        return moveToFront;
    }

    public void removeNode(Node n) {
        getChildren().remove(n);
    }
}

1 个答案:

答案 0 :(得分:0)

您将DraggableNode设置为onMousePressedProperty的EventHandler中的前端。这会将DraggableNode置于其兄弟节点之上,并阻止菜单按钮接收鼠标输入。

为了防止这种情况,我看到两个选项:

  1. 不要通过设置moveToFront = false将DraggableNode设置为前面,或者,如果不可能,
  2. 通过添加

    拖动后再次将DraggableNode设置为后面
    onMouseReleasedProperty().set(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            toBack();
        }
    });
    

    到DraggableNode的init方法。

  3. 对于更通用的解决方案,您可以向DraggableNode

    添加属性
    private BooleanProperty dragInProcessProperty = new SimpleBooleanProperty(false);
    public BooleanProperty dragInProcessProperty() {
        return this.dragInProcessProperty;
    }
    

    在onMouseDraggedProperty中拖动时将属性设置为true,释放鼠标时将属性设置为false

    onMouseReleasedProperty().set(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            dragInProcessProperty.set(false);
        }
    });
    

    并将ChangeListener添加到HBoxandVBoxExampleupdated中的dragInProgressProperty

    node.dragInProcessProperty().addListener(new ChangeListener<Boolean>() {
        @Override
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
            if (!newValue.booleanValue()) {
                mainbox.toFront();
            }
        }
    });
    

    在拖动完成时将节点设置为前面。