2016-04-14 5 views
-1

In meinem Code habe ich einen Event-Handler erstellt, der ursprünglich funktioniert hat; aber nach dem Hinzufügen von mehr Code funktioniert es nicht mehr, so dass ich vor meinen Änderungen wiederhergestellt habe und es immer noch nicht funktioniert. Gibt es etwas, was ich falsch gemacht habe? Außerdem verwende ich Eclipse, wenn das bei der Bestimmung einer Ursache hilfreich ist.JavaFX Event Handler funktioniert nicht mehr

Main.java: Paketanwendung;

import java.util.ArrayList; 

import javafx.application.Application; 
import javafx.event.EventHandler; 
import javafx.fxml.FXMLLoader; 
import javafx.stage.Stage; 
import javafx.scene.Node; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.input.InputEvent; 
import javafx.scene.input.MouseEvent; 


public class Main extends Application { 
    public Parent root; 
    public ChessUtil chess = new ChessUtil(); 
    @Override 
    public void start(Stage primaryStage) { 
     try { 
      root = FXMLLoader.load(getClass().getResource("/Chess.fxml")); 
      Node peice; 
      for(int x = 0; x < 16 ;x++) 
      { 
       peice = root.lookup("#" + chess.whiteID[x]); 
       peice.addEventHandler(MouseEvent.MOUSE_CLICKED, peiceClick); 
       peice = root.lookup("#" + chess.blackID[x]); 
       peice.addEventHandler(MouseEvent.MOUSE_CLICKED, peiceClick); 
      } 
      disablePeicesToggle(chess.blackID, true); 
      Scene scene = new Scene(root,740,740); 
      scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); 
      primaryStage.setScene(scene); 
      primaryStage.show(); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 
    EventHandler peiceClick = new EventHandler<InputEvent>() { 
     public void handle(InputEvent event) { 
      String id = ((Node) event.getSource()).getId(); 
      ArrayList<String> moves = chess.findPeiceMoves(id); 
      System.out.println(moves.size()); 
      if(moves.size() > 0) 
      { 
       System.out.println(moves); 
      } 
      System.out.println("Handling event " + event.getEventType()); 
      event.consume(); 
     } 
    }; 
    public void disablePeicesToggle(String[] idSet, boolean disable) 
    { 
     Node peice; 
     for(int x = 0; x < 16 ;x++) 
     { 
      peice = root.lookup("#" + idSet[x]); 
      peice.setDisable(disable); 
     } 

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

Chess.fxml:

<?xml version="1.0" encoding="UTF-8"?> 

<?import java.lang.*?> 
<?import javafx.scene.layout.*?> 
<?import javafx.scene.layout.AnchorPane?> 

<AnchorPane prefHeight="740.0" prefWidth="740.0" stylesheets="@application/application.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> 
    <children> 
     <AnchorPane id="chessboard" layoutX="10.0" layoutY="10.0" prefHeight="720.0" prefWidth="720.0" stylesheets="@application/application.css" /> 
     <AnchorPane id="board-spaces" layoutX="50.0" layoutY="50.0" prefHeight="640.0" prefWidth="640.0"> 
     <children> 
      <Region id="b7" prefHeight="80.0" prefWidth="80.0" styleClass="bRook" /> 
      <Region id="b3" layoutX="160.0" prefHeight="80.0" prefWidth="80.0" styleClass="bBishop" /> 
      <Region id="b5" layoutX="80.0" prefHeight="80.0" prefWidth="80.0" styleClass="bKnight" /> 
      <Region id="b2" layoutX="240.0" prefHeight="80.0" prefWidth="80.0" styleClass="bQueen" /> 
      <Region id="b1" layoutX="320.0" prefHeight="80.0" prefWidth="80.0" styleClass="bKing" /> 
      <Region id="b4" layoutX="400.0" prefHeight="80.0" prefWidth="80.0" styleClass="bBishop" /> 
      <Region id="b6" layoutX="480.0" prefHeight="80.0" prefWidth="80.0" styleClass="bKnight" /> 
      <Region id="b8" layoutX="560.0" prefHeight="80.0" prefWidth="80.0" styleClass="bRook" /> 
      <Region id="b12" layoutX="240.0" layoutY="80.0" prefHeight="80.0" prefWidth="80.0" styleClass="bPawn" /> 
      <Region id="b10" layoutX="80.0" layoutY="80.0" prefHeight="80.0" prefWidth="80.0" styleClass="bPawn" /> 
      <Region id="b13" layoutX="320.0" layoutY="80.0" prefHeight="80.0" prefWidth="80.0" styleClass="bPawn" /> 
      <Region id="b16" layoutX="560.0" layoutY="80.0" prefHeight="80.0" prefWidth="80.0" styleClass="bPawn" /> 
      <Region id="b9" layoutY="80.0" prefHeight="80.0" prefWidth="80.0" styleClass="bPawn" /> 
      <Region id="b15" layoutX="480.0" layoutY="80.0" prefHeight="80.0" prefWidth="80.0" styleClass="bPawn" /> 
      <Region id="b11" layoutX="160.0" layoutY="80.0" prefHeight="80.0" prefWidth="80.0" styleClass="bPawn" /> 
      <Region id="b14" layoutX="400.0" layoutY="80.0" prefHeight="80.0" prefWidth="80.0" styleClass="bPawn" /> 
      <Region id="w3" layoutX="160.0" layoutY="560.0" prefHeight="80.0" prefWidth="80.0" styleClass="wBishop" /> 
      <Region id="w12" layoutX="240.0" layoutY="480.0" prefHeight="80.0" prefWidth="80.0" styleClass="wPawn" /> 
      <Region id="w10" layoutX="80.0" layoutY="480.0" prefHeight="80.0" prefWidth="80.0" styleClass="wPawn" /> 
      <Region id="w5" layoutX="80.0" layoutY="560.0" prefHeight="80.0" prefWidth="80.0" styleClass="wKnight" /> 
      <Region id="w7" layoutY="560.0" prefHeight="80.0" prefWidth="80.0" styleClass="wRook" /> 
      <Region id="w14" layoutX="400.0" layoutY="480.0" prefHeight="80.0" prefWidth="80.0" styleClass="wPawn" /> 
      <Region id="w1" layoutX="320.0" layoutY="560.0" prefHeight="80.0" prefWidth="80.0" styleClass="wKing" /> 
      <Region id="w2" layoutX="240.0" layoutY="560.0" prefHeight="80.0" prefWidth="80.0" styleClass="wQueen" /> 
      <Region id="w6" layoutX="480.0" layoutY="560.0" prefHeight="80.0" prefWidth="80.0" styleClass="wKnight" /> 
      <Region id="w13" layoutX="320.0" layoutY="480.0" prefHeight="80.0" prefWidth="80.0" styleClass="wPawn" /> 
      <Region id="w16" layoutX="560.0" layoutY="480.0" prefHeight="80.0" prefWidth="80.0" styleClass="wPawn" /> 
      <Region id="w9" layoutY="480.0" prefHeight="80.0" prefWidth="80.0" styleClass="wPawn" /> 
      <Region id="w15" layoutX="480.0" layoutY="480.0" prefHeight="80.0" prefWidth="80.0" styleClass="wPawn" /> 
      <Region id="w11" layoutX="160.0" layoutY="480.0" prefHeight="80.0" prefWidth="80.0" styleClass="wPawn" /> 
      <Region id="w8" layoutX="560.0" layoutY="560.0" prefHeight="80.0" prefWidth="80.0" styleClass="wRook" /> 
      <Region id="w4" layoutX="400.0" layoutY="560.0" prefHeight="80.0" prefWidth="80.0" styleClass="wBishop" /> 
     </children></AnchorPane> 
     <AnchorPane id="board-overlay" layoutX="60.0" layoutY="60.0" prefHeight="640.0" prefWidth="640.0" /> 
    </children> 
</AnchorPane> 

Update: Ich habe meinen Code in einem GitHub Repo setzen. Der vollständige Quellcode ist unter github.com/stitch366/chess/tree/master/chess.

+0

Nein.Was ich suche ist bereits in der fxml – stitch366

+0

Full Source Code ist unter https://github.com/stitch366/chess/tree/master/chess. Außerdem lade ich eine FXML-Datei, und die IDs wurden in der FXML-Datei festgelegt. Es gibt keinen Controller, da ich keine benutzerdefinierte Komponente verwende oder Daten nicht anzeigen kann. – stitch366

+0

Ich habe meinen Code auf GitHub gesetzt, was bedeutet, dass Sie ihn einschließlich der FXML betrachten können; Das Hinzufügen der FXML würde den Weg länger machen, als es bereits ist. Außerdem funktioniert ein Controller nicht für meine Anwendung. – stitch366

Antwort

0

Sie haben einen Ankerbereich (mit der ID board-overlay) über alle anderen Komponenten im Hauptlayout platziert. Es erscheint "oben" (in Z-Reihenfolge), weil Sie es zuletzt dort platziert haben. Wenn der Benutzer auf die Tafel klickt, da dieser Knoten oben ist, empfängt er das Mausereignis; Daher empfängt keines der Region s, die Teile repräsentieren, jemals Mausereignisse und ruft den Listener auf.

Es ist nicht klar, warum Sie dieses Overlay brauchen: Wenn Sie es einfach entfernen, wird alles funktionieren. Wenn Sie es aus anderen Gründen benötigen, können Sie es Abfangen Mausereignisse stoppen, indem mouseTransparent="true" in der FXML Einstellung:

<AnchorPane id="board-overlay" layoutX="60.0" layoutY="60.0" 
    prefHeight="640.0" prefWidth="640.0" mouseTransparent="true"/> 

Möglicherweise Wegthema:

Die Struktur Ihrer Anwendung ist sehr stark nicht empfohlen. Der Zweck der Unterklasse Application besteht darin, den Anwendungslebenszyklus zu verwalten: d. H. Die Anwendung zu starten (die start(...)-Methode) und bei Bedarf sauber herunterzufahren (die stop()-Methode). Es ist nicht Aufgabe der Anwendungsklasse, Benutzerereignisse zu verwalten: Dies ist der explizite Zweck einer Controller-Klasse. I stark empfehlen Refactoring dies, so dass Ihre Ereignisbehandlung in einem Controller verwaltet wird. Ein Grund (der Hauptgrund) ist, dass Ihre Anwendung dadurch viel flexibler wird. (Wenn Sie beispielsweise eine Anwendung haben möchten, in der mehrere Spiele auf verschiedenen Registerkarten angezeigt werden, wäre es sehr schwer, von Ihrem jetzigen Standort aus zu refaktorieren. Die Verwendung eines Controllers zur Verwaltung der Ereignisbehandlung für jede FXML wäre sehr einfach.) Der Grund dafür ist, dass die Verwendung von Nachschlagefunktionen sehr fragil ist: In der Regel hängt es davon ab, dass CSS auf das Szenen-Diagramm angewendet wurde, was standardmäßig nicht der Fall ist, wenn die Szene zum ersten Mal auf dem Bildschirm gerendert wird. Hier scheint es in Ordnung zu sein, wahrscheinlich weil die CSS-IDs explizit gesetzt sind, aber es gibt wirklich keine Garantie, dass dies in zukünftigen Versionen von JavaFX funktionieren wird.

würde ich Ihre Anwendungsklasse Refactoring, so dass es nichts mehr tut, dass die App starten (was seine Aufgabe ist):

package application; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 


public class Main extends Application { 
    @Override 
    public void start(Stage primaryStage) { 
     try { 
      Parent root = FXMLLoader.load(getClass().getResource("/Chess.fxml")); 

      Scene scene = new Scene(root,740,740); 
      scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); 
      primaryStage.setScene(scene); 
      primaryStage.show(); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 
    public static void main(String[] args) { 
     launch(args); 
    } 
} 

und das Ereignis bewegen, um eine Controller-Klasse Handhabung:

package application; 


import java.util.ArrayList; 

import javafx.fxml.FXML; 
import javafx.scene.Node; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.layout.AnchorPane; 

public class Controller { 

    @FXML 
    private AnchorPane root ; 

    private ChessUtil chess = new ChessUtil(); 

    @FXML 
    private void click(MouseEvent event) { 
     String id = ((Node) event.getSource()).getId(); 
     ArrayList<String> moves = chess.findPeiceMoves(id); 
     System.out.println(moves.size()); 
     if(moves.size() > 0) 
     { 
      System.out.println(moves); 
     } 
     System.out.println("Handling event " + event.getEventType()); 
     event.consume(); 
    } 

    public void initialize() { 
     disablePeicesToggle(chess.blackID, true); 
    } 


    public void disablePeicesToggle(String[] idSet, boolean disable) 
    { 
     Node peice; 
     for(int x = 0; x < 16 ;x++) 
     { 
      peice = root.lookup("#" + idSet[x]); 
      peice.setDisable(disable); 
     } 

    } 
} 

aktualisieren dann eben die FXML den Wurzelknoten zu verweisen, und jede Karte Region ein Stück auf die Ereignisbehandlungsmethode in der Steuerung darstellt:

<AnchorPane prefHeight="740.0" prefWidth="740.0" stylesheets="@application/application.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" 
     fx:controller="application.Controller" fx:id="root"> 
    <children> 
     <AnchorPane id="chessboard" layoutX="10.0" layoutY="10.0" prefHeight="720.0" prefWidth="720.0" stylesheets="@application/application.css"/> 
     <AnchorPane id="board-spaces" layoutX="50.0" layoutY="50.0" prefHeight="640.0" prefWidth="640.0"> 
     <children> 
      <Region id="b7" prefHeight="80.0" prefWidth="80.0" styleClass="bRook" onMouseClicked="#click" /> 
      <Region id="b3" layoutX="160.0" prefHeight="80.0" prefWidth="80.0" styleClass="bBishop" onMouseClicked="#click" /> 
      <Region id="b5" layoutX="80.0" prefHeight="80.0" prefWidth="80.0" styleClass="bKnight" onMouseClicked="#click" /> 

      <!-- etc... --> 
     </children></AnchorPane> 
     <AnchorPane id="board-overlay" layoutX="60.0" layoutY="60.0" 
      prefHeight="640.0" prefWidth="640.0" mouseTransparent="true"/> 
    </children> 
</AnchorPane>