РЕДАКТИРОВАТЬ: Проблемы возникают из-за использования SplitPane. Я удалил это, но теперь у меня возникают проблемы с MouseTransparent, см. комментарии
Я столкнулся с проблемой в StackPane, где класс Controller должен управлять переводами узлов с помощью перетаскивания мышью:
По какой-то причине событие .setOnMouseEntered правильно срабатывает всякий раз, когда мышь входит в StackPane. Однако setOnMousePressed (при нажатии на узел в StackPane) вообще не срабатывает, за исключением метки в центре StackPane. Когда я удаляю метку, ничего не срабатывает. Сам StackPane состоит из SplitPane, состоящего из нескольких других узлов.
Некоторые из этих узлов (те, которые предполагается перетаскивать) также имеют некоторое управление событиями setOnMousePressed и т. д., которое срабатывает правильно!
Чтобы лучше понять контекст: я работаю над реализацией игры «Морской бой». В настоящее время я пытаюсь управлять размещением лодки с помощью класса контроллера (чтобы я мог убедиться, что лодка не выходит за пределы или на другую лодку). Класс контроллера (BoatMoveManager) при создании экземпляра создает все эти обработчики событий mouseEvent на самой высокой панели StackPane (GameBoard расширяет StackPane).
public class BoatMoveManager {
GameBoard gB;
public BoatMoveManager(GameBoard g){
gB = g;
//the following mouseEventHandler fires correctly whenever the mouse enters the GameBoard (StackPane)
gB.setOnMouseEntered(event -> {
System.out.println("GameBoard OnMouseEntered");
//the following mouseEventHandler doesn't fire, except on a label in the middle of the GameBoard
gB.setOnMousePressed(event -> {
System.out.println("GameBoard OnMousePressed");
});
Я не понимаю, почему событие срабатывает с меткой, а не с остальными узлами в GameBoard... (Может быть дело в том, что метка находится непосредственно "внутри" GameBoard, а другие узлы находятся в верхняя часть горизонтального сплиттера?)
Например, вот конструктор для GameBoard:
public class GameBoard extends StackPane {
private SplitPane splitter;
private TilePane gameZone;
private TabZone tabs;
private Grid playerGrid, opponentGrid, playerHarbor, opponentHarbor;
private FlowPane playerGrids, opponentGrids, playerZone, opponentZone;
private Score playerScore, opponentScore;
private Label popup;
private static HBox playerHBox, opponentHBox;
private static VBox playerVBox, opponentVBox;
private static BoatMoveManager bMM;
private List<Boat> playerBoatsList = new ArrayList<Boat>(), opponentBoatsList = new ArrayList<Boat>() ;
public GameBoard(){
super();
playerGrid = new Grid('G','H');
opponentGrid = new Grid('G','H');
playerHarbor = new Grid('H','H');
opponentHarbor = new Grid('H','H');
bMM = new BoatMoveManager(this);
for(int i = 1 ; i < 5 ; ++i){
playerBoatsList.add(new Boat(i, playerGrid, playerHarbor));
opponentBoatsList.add(new Boat(i, opponentHarbor, opponentGrid));
}
playerGrid.drawBoat(playerBoatsList.get(0), 3, 4);
playerGrid.drawBoat(playerBoatsList.get(1), 3, 5);
playerGrid.drawBoat(playerBoatsList.get(2), 3, 6);
playerGrid.drawBoat(playerBoatsList.get(3), 3, 7);
playerScore = new Score();
opponentScore = new Score();
gameZone = new TilePane(Orientation.HORIZONTAL);
gameZone.setStyle("-fx-background-color: lightgray");
playerHBox = new HBox();
playerHBox.getChildren().addAll(playerHarbor, playerGrid);
playerHBox.setSpacing(Grid.getUnit());
playerVBox = new VBox();
playerVBox.getChildren().addAll(playerScore,playerHBox);
playerVBox.maxWidthProperty().bind(gameZone.widthProperty().divide(2));
playerScore.setAlignment(Pos.CENTER);
opponentHBox = new HBox();
opponentHBox.getChildren().addAll(opponentGrid, opponentHarbor);
opponentHBox.setSpacing(Grid.getUnit());
opponentVBox = new VBox();
opponentVBox.getChildren().addAll(opponentScore,opponentHBox);
opponentScore.setAlignment(Pos.CENTER);
gameZone.getChildren().addAll(playerVBox, opponentVBox);
gameZone.setHgap(Grid.getUnit()*3);
gameZone.setAlignment(Pos.CENTER);
gameZone.setSnapToPixel(false);
tabs = new TabZone();
splitter = new SplitPane();
splitter.setOrientation(Orientation.VERTICAL);
splitter.setDividerPositions(0.75f,0.25f);
splitter.getItems().addAll(gameZone,tabs);
splitter.setOnDragEntered(event ->{
BoatMoveManager.setTarget(splitter);
});
popup = new Label("uninitialized");
this.getChildren().addAll(splitter,popup);
this.setOnDragEntered(event -> {
BoatMoveManager.setTarget(this);
});
}
Метка, о которой я говорю, — «всплывающее окно», которая добавляется в самый конец конструктора вместе с «разделителем» в
this.getChildren().addAll(splitter,popup);
Но примите во внимание тот факт, что даже когда я его не добавляю, такие события, как MousePressed, не срабатывают через GameBoard...
Вот макет GameBoard, чтобы прояснить ситуацию (расположение сеток и лодок говорит само за себя): (Откройте это изображение в новой вкладке, чтобы просмотреть его в полном размере) Я надеюсь, что это не слишком загромождено, чтобы понять, что я пытаюсь сделать.. И почему это не работает.
2 ответа
Я действительно не уверен на данный момент. Мне пришлось бы протестировать код на своем компьютере, чтобы знать наверняка, но попробуйте
this.setMouseTransparency(true);
Это приведет к тому, что на саму панель стека нельзя будет щелкнуть. Также для дальнейшего использования вы можете опустить «это» в начале ваших вызовов GameBoard. Совершенно законно вызывать getChildren().add(node), если ваш класс расширяет StackPane.
this.setMouseTransparent(true)
также делает все узлы внутри GameBoard StackPane прозрачными для мыши...
Столкнувшись с той же проблемой (снова)..
Я считаю, что StackPane - это ваша проблема. Они не любят проходить события явно.. В моем случае установка: stackPane.setPickOnBounds(false);
Было моим решением.
Я надеюсь, что это решит проблему для вас ... возможно, ошибка?
Похожие вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.