在buttonPressed方法的范围内,javafx类变量为空

时间:2017-05-23 17:20:52

标签: java javafx

我有以下代码

TTTControl类:

public class TTTControl extends Application implements EventHandler<ActionEvent> {

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

    @Override
    public void start(Stage stage) throws Exception {
        String resource = "TTTGui.fxml";
        Parent root = FXMLLoader.load(getClass().getResource(resource));

        int window_width = 800;
        int window_height = 380;
        stage.setScene(new Scene(root, window_width, window_height));
        stage.show();
    }

    @Override
    public void handle(ActionEvent event) {
        // Könnte man ggfs. in der Zukunft noch benutzen
        System.out.println("Event!");
    }
}

控制器类:

public class Controller {
    int n = 3;
    Button buttons[][] = new Button[n][n];

    EventManager em = new EventManager();

    Controller() throws Exception {
        String resource = "TTTGui.fxml";
        Parent root = FXMLLoader.load(getClass().getResource(resource));

        for (int i=0; i < this.n; i++) {
            for (int j=0; j < this.n; j++) {
                String row = Integer.toString(i);
                String col = Integer.toString(j);
                Button btn = (Button) root.lookup("#"+row+col);
                btn.setStyle("-fx-base: white;");
                this.buttons[i][j] = btn;
            }
        }
    }

    // Funktion die beim Klicken eines Buttons mit dem onAction="#buttonPressed" Attribut ausgeführt wird
    public void buttonPressed(ActionEvent event) {

        if (((Button) event.getSource()).getStyle() == "-fx-base: green;" ||
            ((Button) event.getSource()).getStyle() == "-fx-base: red;") {
            // der Vollständigkeit halber wird hier auch noch ausgegeben, dass es zwar ein ClickEvent gab, aber das Feld schon belegt war
            System.out.println("Spieler 1 hat " + ((Button) event.getSource()).getId() + " gedrückt.");
            System.out.println("Dieses Feld ist jedoch schon besetzt.");
        } else {
            if (em.getActivePlayer() == "One") {
                System.out.println("Spieler 1 hat " + ((Button) event.getSource()).getId() + " gedrückt.");
                ((Button) event.getSource()).setStyle("-fx-base: green;");
                em.setActivePlayer("Two");

                if (em.checkWin("-fx-base: green;", this.buttons) == true) {
                    System.out.println("Spieler Eins hat gewonnen!");
                    neuesSpiel();
                }
            } else if (em.getActivePlayer() == "Two") {
                System.out.println("Spieler 1 hat " + ((Button) event.getSource()).getId() + " gedrückt.");
                ((Button) event.getSource()).setStyle("-fx-base: red;");
                em.setActivePlayer("One");

                if (em.checkWin("-fx-base: red;", this.buttons) == true) {
                    System.out.println("Spieler Zwei hat gewonnen!");
                    neuesSpiel();
                }
            }
        }
    }
}

eventmanager进行:

public class EventManager {
    private String activePlayer;

    // Konstruktur von der Klasse mit ein paar Variablen die initialisiert werden
    EventManager() {
        this.activePlayer = "One";
    }

    public boolean checkWin(String color, Button[][] buttons) {
        // [Reihe][Spalte]
        // horizontal
        if (buttons[0][0].getStyle() == color && buttons[0][1].getStyle() == color && buttons[0][2].getStyle() == color) {
            return true;
        }
        else if (buttons[1][0].getStyle() == color && buttons[1][1].getStyle() == color && buttons[1][2].getStyle() == color) {
            return true;
        }
        else if (buttons[2][0].getStyle() == color && buttons[2][1].getStyle() == color && buttons[2][2].getStyle() == color) {
            return true;
        }
        // vertikal
        else if (buttons[0][0].getStyle() == color && buttons[1][0].getStyle() == color && buttons[2][0].getStyle() == color) {
            return true;
        }
        else if (buttons[0][1].getStyle() == color && buttons[1][1].getStyle() == color && buttons[2][1].getStyle() == color) {
            return true;
        }
        else if (buttons[0][2].getStyle() == color && buttons[1][2].getStyle() == color && buttons[2][2].getStyle() == color) {
            return true;
        }
        // diagonal
        else if (buttons[0][0].getStyle() == color && buttons[1][1].getStyle() == color && buttons[2][2].getStyle() == color) {
            return true;
        }
        else if (buttons[0][2].getStyle() == color && buttons[1][1].getStyle() == color && buttons[2][0].getStyle() == color) {
            return true;
        }
        return false;
    }

    // Getter und Setter Methoden für die private Variablen
    public void setActivePlayer(String activePlayer) {
        this.activePlayer = activePlayer;
    }

    public String getActivePlayer() {
        return this.activePlayer;
    }
}

所以,我尝试创建一个控制器类,例如应该处理所有按钮事件(我猜这是控制器在这种情况下的用途)。因为我需要Parent root我猜测将根注入控制器意味着再次在那个地方加载它.... Buuut这不起作用我得到了跟随< / p>

错误:

Exception in Application start method
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
    at java.lang.Thread.run(Unknown Source)
Caused by: javafx.fxml.LoadException: 
/C:/Users/Ibrahim/git/nicolle_informatik/bin/vl06/TTTGui.fxml:21

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
    at javafx.fxml.FXMLLoader.access$700(FXMLLoader.java:103)
    at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:934)
    at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:971)
    at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:220)
    at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:744)
    at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
    at vl06.TTTControl.start(TTTControl.java:20)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    ... 1 more
Caused by: java.lang.IllegalAccessException: Class sun.reflect.misc.ReflectUtil can not access a member of class vl06.Controller with modifiers ""
    at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
    at java.lang.Class.newInstance(Unknown Source)
    at sun.reflect.misc.ReflectUtil.newInstance(Unknown Source)
    at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:927)
    ... 22 more
Exception running application vl06.TTTControl

1 个答案:

答案 0 :(得分:1)

出现异常是因为控制器中的构造函数不是公共的。

您的代码中还有许多其他错误。

您正在加载控制器中FXML中定义的UI的第二个副本:

Controller() throws Exception {
    String resource = "TTTGui.fxml";
    Parent root = FXMLLoader.load(getClass().getResource(resource));

    // ...
}

这将创建FXML文件的根元素的第二个实例,以及其中包含的所有内容的新实例。显然,这与您在Scene方法中start中显示的实例不同。因此按钮与显示的按钮不同,按钮上的配置无效。

您需要使用FXML中常用的fx:id属性将根元素注入控制器,并使用@FXML注释:

public class Controller {
    int n = 3;
    Button buttons[][] = new Button[n][n];

    EventManager em = new EventManager();

    @FXML
    private Parent root ;

   // ...
}

然后将fx:id="root"添加到FXML文件的根元素。

此外,您试图在控制器的构造函数中引用FXML的元素,而不是initialize()方法。如描述here,必须在注入FXML中定义的元素之前调用构造函数,因此不能在那里访问它们。

所以你需要像

这样的东西
public class Controller {

    int n = 3;
    Button buttons[][] = new Button[n][n];

    EventManager em = new EventManager();

    @FXML
    private Parent root ;

    public void initialize() {

        for (int i=0; i < this.n; i++) {
            for (int j=0; j < this.n; j++) {
                String row = Integer.toString(i);
                String col = Integer.toString(j);
                Button btn = (Button) root.lookup("#"+row+col);
                btn.setStyle("-fx-base: white;");
                this.buttons[i][j] = btn;
            }
        }
    }

   // ...
}

最后,您有一些基本的Java错误,超出了本问题的范围。例如。你应该阅读How do I compare strings in Java?