Javafx 如何将菜单按钮设置为始终位于其他组件(如HBox)的顶部(可拖动)

Javafx 如何将菜单按钮设置为始终位于其他组件(如HBox)的顶部(可拖动),javafx,Javafx,我有一个父VBox,它有一个菜单按钮和一个可拖动的HBox。当我拖动HBox时,菜单按钮没有响应(因为HBox设置在菜单按钮上)。如果HBox是可拖动的,我如何始终设置其顶部的菜单按钮 HBoxandVBoxExampleupdated.java: import DraggableNode; import javafx.scene.chart.NumberAxis; import javafx.application.Application; import javafx.geometry.In

我有一个父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);
    }
}
DragableNode.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);
    }
}
导入javafx.event.EventHandler;
导入javafx.scene.Cursor;
导入javafx.scene.Node;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.layout.Pane;
导入javafx.scene.layout.StackPane;
公共类DragTableNode扩展StackPane{
私人双x=0;
私人双y=0;
专用双鼠标=0;
专用双鼠标=0;
私有节点视图;
私有布尔值=false;
私有布尔moveToFront=true;
私人双码=0;
私有双新闻大小=0;
公共DragTableNode(){
init();
}
公共DragTableNode(节点视图){
this.view=视图;
getChildren().add(视图);
setMouseTransparent(真);
init();
}
私有void init(){
onMousePressedProperty().set(新的EventHandler()){
@凌驾
公共无效句柄(MouseeEvent事件){
getScene().setCursor(Cursor.HAND);
//记录当前鼠标在节点上的X和Y位置
mousex=event.getSceneX();
mousey=event.getSceneY();
x=getLayoutX();
y=getLayoutY();
if(isMoveToFront()){
toFront();
}
}
});
onMouseDraggedProperty().set(新的EventHandler()){
@凌驾
公共无效句柄(MouseeEvent事件){
double offsetX=event.getSceneX()-mousex;
x+=抵销x;
双刻度x=x;
System.out.println(“:”+scaledX);
如果(缩放X>0)
{
返回;
}
setLayoutX(scaledX);
拖动=假;
mousex=event.getSceneX();
event.consume();
}
});
onMouseClickedProperty().set(新的EventHandler()){
@凌驾
公共无效句柄(MouseeEvent事件){
拖动=假;
}
});
}
/**
*@返回拖动
*/
受保护的布尔IsDraging(){
返回拖动;
}
/**
*@返回视图
*/
公共节点getView(){
返回视图;
}
/**
*@param moveToFront
*移动到前面设置
*/
公共无效设置moveToFront(布尔值moveToFront){
this.moveToFront=moveToFront;
}
/**
*@返回moveToFront
*/
公共布尔值isMoveToFront(){
返回到前面;
}
公共void removeNode(节点n){
getChildren().remove(n);
}
}

您可以在
onMousePressedProperty的事件处理程序中将DragTableNode设置在前面。这会将DragTableNode置于其同级节点之上,并阻止菜单按钮接收鼠标输入

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

  • 不要通过设置
    moveToFront=false
    将DragableNode设置到前面,或者,如果不可能
  • 通过添加将拖动后的DragTableNode再次设置为back

    onMouseReleasedProperty().set(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            toBack();
        }
    });
    
    在鼠标拖动onMouseDraggedProperty时将属性设置为
    true
    ,释放鼠标时将属性设置为
    false

    onMouseReleasedProperty().set(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            dragInProcessProperty.set(false);
        }
    });
    
    onMouseReleasedProperty().set(新的EventHandler()){
    @凌驾
    公共无效句柄(MouseeEvent事件){
    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();
            }
        }
    });
    
    node.dragInProcessProperty().addListener(新的ChangeListener()){
    @凌驾
    
    public void changed(observeValue您将DragTableNode设置在MousePressedProperty
    的事件处理程序的前面。这将DragTableNode置于其同级节点之上,并阻止菜单按钮接收鼠标输入

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

  • 不要通过设置
    moveToFront=false
    将DragableNode设置到前面,或者,如果不可能
  • 通过添加将拖动后的DragTableNode再次设置为back

    onMouseReleasedProperty().set(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            toBack();
        }
    });
    
    在鼠标拖动onMouseDraggedProperty时将属性设置为
    true
    ,释放鼠标时将属性设置为
    false

    onMouseReleasedProperty().set(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            dragInProcessProperty.set(false);
        }
    });
    
    onMouseReleasedProperty().set(新的EventHandler()){
    @凌驾
    公共无效句柄(MouseeEvent事件){
    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();
            }
        }
    });
    
    node.dragInProcessProperty().addListener(新的ChangeListener()){
    @凌驾
    
    更改公众假期(ObservableValue您想将
    菜单按钮
    堆叠在
    HBox
    的顶部吗?或者,您只是想将两个节点安排在彼此相邻的位置吗?@ItachiUchiha:hi…实际上,当我拖动HBox时,我的HBox容器激活,当我拖动它时,它会出现在菜单按钮上,因为我的菜单按钮没有响应ng所以我想回应它。如果hbox继续它…@ItachiUchiha:检查代码…:)如果一个节点是可拖动的,而您将其放置在另一个节点的顶部,则后者无法接收任何用户输入。如果您希望HBox不阻止鼠标事件,可以将其设置为true。但是,我在您的代码中找不到StackPane。HBox如何将自身放置在菜单按钮的顶部?是否要将
    菜单按钮
    堆叠在e
    HBox
    ?或者,你只是想把两个节点安排在彼此相邻的位置吗?@ItachiUchiha:嗨……事实上,当我