setOnMouseClicked无法正常工作

时间:2016-02-06 15:49:23

标签: java javafx-8

我一直致力于我的纸牌游戏的GUI部分。

我正在做的是在玩家点击其中一张卡的ImageView时显示确认对话框。

事情一直在顺利进行,但有一个我无法修复的错误。 反复单击ImageView并关闭警告对话框后。该对话框无法在后续调用中呈现其正文。

这是一个错误吗?还是我做错了?这是我在stackoverflow中的第一个问题,希望我能尽快找到帮助。谢谢!

我带走了大部分游戏逻辑代码,但它看起来仍然很长:

public class Game extends Application implements IGame {
    final Alert confirmationDialog = new Alert(AlertType.CONFIRMATION);
    final Alert errorDialog = new Alert(AlertType.INFORMATION);
    Player currentPlayer;

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

    @Override
    public void start(Stage startStage) throws Exception {
        // initialization
        startStage.setTitle("Welcome to The Card Game");

        ChoiceBox<Integer> choiceBox = new ChoiceBox<Integer>();
        Label promptLabel = new Label("Number of Players:");
        promptLabel.setStyle("-fx-font: 30 Arial");

        choiceBox.getItems().addAll(2, 3, 4);
        choiceBox.setValue(2);
        choiceBox.setStyle("-fx-font: 20 Arial");

        VBox outerLayout = new VBox(50);
        HBox innerLayout = new HBox(30);
        innerLayout.getChildren().addAll(promptLabel, choiceBox);
        innerLayout.setStyle("-fx-alignment: center;");

        Button buttonStart = new Button("START GAME");
        buttonStart.setOnAction(e -> {
            startGame(choiceBox.getValue());
            startStage.close();
        });
        outerLayout.setStyle("-fx-font: 20 Arial; -fx-alignment: center; -fx-padding: 100; -fx-background-color: #993333");
        outerLayout.getChildren().addAll(innerLayout, buttonStart);

        Scene scene = new Scene(outerLayout);
        startStage.setMinWidth(700);
        startStage.setMinHeight(500);
        startStage.setScene(scene);
        startStage.show();
    }       

    void startGame(int numberOfPlayers) {
        // initialize UI components
        showMessage("The game has started.");
        currentPlayer = players[playerIndex];
        getUserSelection();

        gameStage.setTitle("The Card Game");
        Scene scene = new Scene(mainLayout);
        scene.setFill(null);
        gameStage.setScene(scene);
        gameStage.show();
    }

    @Override
    public void getUserSelection() {
        showMessage("It is Player " + (playerIndex+1) + "'s turn.");
        playerLabel.setText("Player " + (playerIndex+1));
        if (currentPlayer.isPlayable(pileTop)) {
            counter=0;
            playerHand.getChildren().clear();
            for(int i=0; i<currentPlayer.hand.size(); i++) {
                Card playerCard = currentPlayer.hand.get(i);
                playerHand.getChildren().add(playerCard.imageView);
                playerCard.imageView.setOnMouseClicked(e -> UserSelectionDialog(playerCard));
            }
            playTable.setBottom(playerHand);
        } else {
            counter++;
            if (currentPlayer.hand.size() < 5) {
                showMessage("Player " + (playerIndex+1) + " draws a card.");
                currentPlayer.addCard(stock.remove(stock.size()-1));
                if (stock.isEmpty()) {
                    showMessage("Stock pile is exhausted, shuffling discard pile..");
                    shuffle();
                }
            }
            showMessage("Player " + (playerIndex+1) + " passes the round.");
            if (counter == playerNo) end();
            else {
                nextPlayer();
                getUserSelection();
            }
        }
    }

    void UserSelectionDialog(Card playerCard) {
        confirmationDialog.setTitle("Confirmation Dialog");
        confirmationDialog.setHeaderText("You are about to play the " + playerCard + ".");
        confirmationDialog.setContentText("Confirm playing this card?");
        confirmationDialog.getButtonTypes().setAll(ButtonType.YES, ButtonType.CANCEL);
        Optional<ButtonType> result = confirmationDialog.showAndWait();
        if (result.get() == ButtonType.YES){
            if (playerCard.match(pileTop)) {
                currentPlayer.playCard(playerCard);
                showMessage("Player " + (playerIndex+1) + " discarded " + playerCard);
                pile.add(playerCard);
                pileTop = pile.get(pile.size()-1);
                pilePane.getChildren().add(pileTop.imageView);

                // end game if player's hand is empty
                if (currentPlayer.hand.isEmpty()) end();
                else {
                    nextPlayer();
                    getUserSelection();
                }
            }
            else {
                errorDialog.setTitle("Message");
                errorDialog.setHeaderText("Cannot play this card.");
                errorDialog.setContentText("Your card does not match the rank and suit.");
                errorDialog.showAndWait();
            }
        }
    }
}

可能是什么问题?我试图自己解决这个问题,但无济于事。 :(

我也意识到问题出现在固定数量的mouseClick事件之后。 我怀疑应用程序在一段时间后会从程序中分离出来吗?

当我执行非GUI 的操作时,鼠标点击事件正常工作,例如:

playerCard.imageView.setOnMouseClicked(e -> System.out.println("TEST"));

然而,即使是简单的 GUI功能,例如在一系列事件之后将项目添加到ListView中也不起作用

playerCard.imageView.setOnMouseClicked(e -> listView.add("TEST"));


屏幕截图:

前10个警报没问题

No problem for the first 10 alerts

此后警报正文变为空白

Alert body becomes blank after that

修改

在我看来,存在一些问题,可能是内存泄漏导致JavaFX UI挂起。随着我向UI组件添加更多负载,UI似乎挂得更快。

即:我添加了另一行来将我的舞台设置为全屏,它会导致用户界面在5秒内挂起到我的应用程序中。

 gameStage.setFullscreen(true);


编辑2

我已使用此方法test memory consumption of a java program with eclipse测试了我的应用程序,并显示了80 MB的常量内存使用情况。因此,内存可能不是导致此问题的原因。

1 个答案:

答案 0 :(得分:0)

显然,在重新启动Java Eclipse IDE之后,我无法重现该问题。不知道为什么,但我想这个问题不再有效。