首页 > 解决方案 > JavaFX - StackPane 与窗格作为 EventDispatcher

问题描述

在事件调度程序窗格中发生鼠标按下事件。当事件发生时,窗格应显示其组合框的上下文菜单。

如果仅将事件分配到窗格之一,则效果很好。当事件被分配到窗格一和窗格二时,窗格一的上下文菜单不会显示。我想这与事件尾部和事件消耗有关。

到目前为止,我还没有看过 JDK 本身的 EventDispatcher 类。

这是我到目前为止得到的:

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

/**
 *
 * @author Robert
 */
public class EventDispatcherExample extends Application {

    private Group root;
    private StackPane cStackPane;
    private Pane cPaneEventDispatcher;
    private Pane cPaneOne;
    private ComboBox cComboBox;
    private Pane cPaneTwo;

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        root = new Group();

        cStackPane = new StackPane();
        cStackPane.setPrefHeight(200.0);
        cStackPane.setPrefWidth(200.0);

        cPaneEventDispatcher = new Pane();
        cPaneEventDispatcher.setPrefHeight(200.0);
        cPaneEventDispatcher.setPrefWidth(200.0);
        cPaneEventDispatcher.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                //System.out.println("Mouse pressed in Pane ED.");
                cPaneOne.fireEvent(event);
                cPaneTwo.fireEvent(event);
            }
        });

        cPaneOne = new Pane();
        cPaneOne.setPrefHeight(200.0);
        cPaneOne.setPrefWidth(200.0);
        cPaneOne.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                //System.out.println("Mouse pressed in Pane One.");
                cComboBox.show();
            }

        });
        ObservableList<String> observableList = FXCollections.observableArrayList();
        observableList.add("1");
        observableList.add("2");
        observableList.add("3");
        cComboBox = new ComboBox();
        cComboBox.setLayoutX(50.0);
        cComboBox.setLayoutY(50.0);
        cComboBox.setPrefHeight(30.0);
        cComboBox.setPrefWidth(100.0);
        cComboBox.setItems(observableList);

        cPaneTwo = new Pane();
        cPaneTwo.setPrefHeight(200.0);
        cPaneTwo.setPrefWidth(200.0);
        cPaneTwo.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                //System.out.println("Mouse pressed in Pane Two.");
                //Something will happen because of selected item in Combo Box of pane one...
            }
        });

        cPaneOne.getChildren().add(cComboBox);
        // add the nodes in reverse order
        cStackPane.getChildren().add(cPaneTwo);
        cStackPane.getChildren().add(cPaneOne);
        cStackPane.getChildren().add(cPaneEventDispatcher);
        root.getChildren().add(cStackPane);

        Scene scene = new Scene(root, 200, 200);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

}

任何想法如何处理这个?

标签: javafxevent-dispatching

解决方案


经过一些想法后,我得到了一个至少有效的解决方案:

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

/**
 *
 * @author Robert
 */
public class EventDispatcherExample extends Application {

    private Group root;
    private StackPane cStackPane;
    private Pane cPaneEventDispatcher;
    private Pane cPaneOne;
    private ComboBox cComboBox;
    private boolean cComboBoxClicked = false;
    private Pane cPaneTwo;

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

    public boolean isComboBoxClicked() {
        if (cComboBoxClicked == true) {
            cComboBox.show();
        } else {
            cComboBox.hide();
        }
        return cComboBoxClicked;
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        root = new Group();

        cStackPane = new StackPane();
        cStackPane.setPrefHeight(200.0);
        cStackPane.setPrefWidth(200.0);

        cPaneEventDispatcher = new Pane();
        cPaneEventDispatcher.setPrefHeight(200.0);
        cPaneEventDispatcher.setPrefWidth(200.0);
        cPaneEventDispatcher.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                //System.out.println("Mouse pressed in Pane ED.");
                cPaneOne.fireEvent(event);
                cPaneTwo.fireEvent(event);
            }
        });

        cPaneOne = new Pane();
        cPaneOne.setPrefHeight(200.0);
        cPaneOne.setPrefWidth(200.0);
        cPaneOne.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                //System.out.println("Mouse pressed in Pane One.");

                Rectangle rect = new Rectangle(cComboBox.getLayoutX(), cComboBox.getLayoutY(),
                        cComboBox.getPrefWidth(), cComboBox.getPrefHeight());
                cComboBoxClicked = rect.contains(event.getX(), event.getY());
            }
        });

        ObservableList<String> observableList = FXCollections.observableArrayList();
        observableList.add("1");
        observableList.add("2");
        observableList.add("3");
        cComboBox = new ComboBox();
        cComboBox.setLayoutX(50.0);
        cComboBox.setLayoutY(50.0);
        cComboBox.setPrefHeight(30.0);
        cComboBox.setPrefWidth(100.0);
        cComboBox.setItems(observableList);

        cComboBox.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                // if cComboBoxSelectedIndex == 1 do Color on pane two
                // if cComboBoxSelectedIndex == 2 do Size on pane two
                // if cComboBoxSelectedIndex == 3 do ...
                //System.out.println("newValue " + newValue);
            }
        });

        cPaneTwo = new Pane();
        cPaneTwo.setPrefHeight(200.0);
        cPaneTwo.setPrefWidth(200.0);
        cPaneTwo.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                //System.out.println("Mouse pressed in Pane Two.");

                boolean cComboBoxClicked = isComboBoxClicked();
                if (cComboBoxClicked){
                    //System.out.println("Skip code internally managed by pane two.");
                    return;
                }

                // Internal code of pane two
                //...
            }
        });

        cPaneOne.getChildren().add(cComboBox);
        // add the nodes in reverse order
        cStackPane.getChildren().add(cPaneTwo);
        cStackPane.getChildren().add(cPaneOne);
        cStackPane.getChildren().add(cPaneEventDispatcher);
        root.getChildren().add(cStackPane);

        Scene scene = new Scene(root, 200, 200);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

}

也许在其他人的时间里会出现更好的方法。很期待...


推荐阅读