gpt4 book ai didi

JavaFX : Button never sets a graphic

转载 作者:行者123 更新时间:2023-12-01 11:24:43 25 4
gpt4 key购买 nike

编辑:

我的代码已制作了 MCVE 版本来帮助调试它。它重现了我的错误。我的代码的目的是做一个内存游戏。这意味着,当轮到你时,你“打开”一张牌,然后是另一张。如果它们成对,它们就不会被翻转,而是保持开放状态。否则,您将它们翻过来并尝试在下一轮中找到一对。

简单地说,这个错误是:当你打开回合中的第二张牌并且两张牌没有形成一对时,第二张牌永远不会被打开!

希望我的这个版本的代码能够帮助您找到错误,这对我有很大帮助!

我已将代码放在Github上:https://gist.github.com/anonymous/e866671d80384ae53b53(您会发现它附在问题的末尾)

<小时/>

问题说明

我在 JavaFX 中做一个小内存游戏时很有趣,我遇到了这种奇怪的行为,我单击的卡片(由扩展 Button 类的自定义类表示)永远不会更改显示的图像。

通常,当我单击卡片时,它会通过更改其显示的图形来“打开”自身。奇怪而烦人的是,它只发生在特定情况下。

当我“打开”玩家回合的第一张牌时,我的牌的行为是正确的。当我“打开”第二张并且两张牌都是一对时,它也可以工作。遗憾的是,它仅在我想打开第二张卡并且它与第一张卡不匹配的情况下才起作用。

我通过添加 openCard()closeCard() 方法修改了 Button 类。这些方法将在按钮卡上设置特定的图形。

我现在将展示一些代码,但很难判断是什么部分导致了这种行为的发生。更重要的是,我正在使用 Eclipse,但不可能弄清楚如何使用断点调试 JavaFX 应用程序(我正在使用控制台打印),因为当我到达断点并开始爬行代码时,该应用程序最终会崩溃。

<小时/>

代码

首先是修改后的Button类:

public class Card extends Button{
private String cardDesign;

public Card(int row, int column){
this.setGraphic(new ImageView("/resources/card_back.png"));
this.setBackground(new Background(new BackgroundFill(Color.SLATEGRAY,
new CornerRadii(6), null)));
}

public void setOpenCardDesign(String design){ cardDesign = design; }

public void openCard(){ this.setGraphic(new ImageView(cardDesign)); }

public void closeCard(){
this.setGraphic(new ImageView("/resources/card_back.png"));
}

}

现在是 Controller 类,事件设置在 MouseEvent 上。该 Controller 中有更多代码(例如检查是否有一对),但这不是问题,我认为问题已经出现在我调用打开卡的方法的行上。我在这里使用 getSource() 方法,因为我的卡片排列在 gridPane 中,我需要知道点击了哪一张。

@Override
public void handle(MouseEvent event) {
//Get the card that was clicked on
Card card = (Card) event.getSource();
//Open the card
card.openCard();
//Do some more after this...

}

<小时/>

据我所知,这差不多是这样。

如前所述,我尝试检查是否正在调用 openCard() 方法。正如我的控制台中打印的一些评论所示。我什至在设置图形的行之前和之后添加了一些控制台打印,它们都显示出来了。我无法确定当我的应用到达 setGraphic() 行时会发生什么,因为我的应用中没有显示任何内容(卡片保持关闭状态)。

任何提示都会有帮助,因为我现在正在慢慢陷入疯狂。预先感谢您。

<小时/>

我的代码的 MCVE 版本

卡片对象:Card.java

package memory;

import javafx.scene.control.Button;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.paint.Color;

public class Card extends Button{
//-------------------------------------------------
//Store the position of the card
private int row;
private int column;
//-------------------------------------------------
//Constructor
public Card(int row, int column){
//Give the cards a specific color at init
this.setBackground(new Background(new BackgroundFill(Color.DEEPSKYBLUE,
new CornerRadii(6), null)));
this.setText("CLOSED");
this.row = row;
this.column = column;
}
//-------------------------------------------------
//Open the card
public void openCard(){
System.out.println("OPEN");
//Cards are red when open
this.setBackground(new Background(new BackgroundFill(Color.RED,
new CornerRadii(6), null)));
this.setText("OPEN");
}
//-------------------------------------------------
//Close the card
public void closeCard(){
System.out.println("CLOSE");
//Cards are blue when closed
this.setBackground(new Background(new BackgroundFill(Color.DEEPSKYBLUE,
new CornerRadii(6), null)));
this.setText("CLOSED");
}
//-------------------------------------------------
//Getters for row and column info
public int getRow() { return row; }
public int getColumn() { return column; }
}

主要部分(包括应用程序的 View 和起点):Main.java

package memory;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Main extends Application {

//-------------------------------------------------
//The layout and the cards
GridPane gridCard = new GridPane();
static Card [][] cardArray;
//The event handler
private static EventHandler<MouseEvent> handler;
//The array which remembers the pairs and the reminder of last open card
static int[][] indexArray;
static int index;
//Boolean array to check if the card is already open
static boolean[][] isOpen;
//Number of pairs to find
static int pairs = 5;
//-------------------------------------------------
//Cheap main
public static void main(String[] args) {
Application.launch(args);
}
//-------------------------------------------------
@Override
public void start(Stage primaryStage) throws Exception {

//Init the event handler
handler = new Controller();

//Some formatting for the grid pane
gridCard.setHgap(10);
gridCard.setVgap(10);
gridCard.setPadding(new Insets(0, 10, 0, 10));
gridCard.setAlignment(Pos.CENTER);

//Creating our card board, index array and bool array
cardArray = new Card [2][5];
indexArray = new int [2][5];
isOpen = new boolean [2][5];
//Adding the cards to our card array
for(int i = 0; i < 2; i++){
for(int j = 0; j < 5; j++){
cardArray[i][j] = new Card(i, j);
//Make those buttons look like cards
cardArray[i][j].setPrefHeight(100);
cardArray[i][j].setPrefWidth(70);
//Register the event
cardArray[i][j].addEventHandler(MouseEvent.MOUSE_CLICKED, gameController());
//Add those cards
gridCard.add(cardArray[i][j], j, i);
//Set the pairs (no randomness here)
indexArray[i][j] = j+1;
}
}
//Print out the indexes of all the cards
System.out.println("----------------");
System.out.println("Card indexes :");
for (int i = 0; i < indexArray.length; i++) {
System.out.println();
for (int j = 0; j < indexArray[0].length; j++) {
System.out.print(indexArray[i][j]+ " | ");
}
System.out.println();
}
System.out.println("----------------");

//Set BorderPane
BorderPane root = new BorderPane();
root.setBackground(new Background(new BackgroundFill(Color.BLACK,
CornerRadii.EMPTY, null)));
root.setCenter(gridCard);

//Set the stage
primaryStage.setScene(new Scene(root));
primaryStage.setTitle("Memory Test");
primaryStage.show();



}
//-------------------------------------------------
//Getter for the event handler
public static EventHandler<MouseEvent> gameController() {
return handler;
}
//-------------------------------------------------
//Getter, Setter and "resetter" for the index
public static void resetIndex() { index = 0; }
public static int getIndex() { return index; }
public static void setIndex(int i) {
index = i;
}
//-------------------------------------------------
}

Controller :Controller.java

package memory;

import javafx.event.EventHandler;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.input.MouseEvent;

public class Controller implements EventHandler<MouseEvent>{

//-------------------------------------------------
@Override
public void handle(MouseEvent event) {
//Get the card which cas clicked on
Card card = (Card) event.getSource();

//If the card was already open, don't do anything
if (!Main.isOpen[card.getRow()][card.getColumn()]) {
//Open the card
card.openCard();

//We opened the first card of the turn
if (Main.getIndex() == 0) {

//Set the card as open
Main.isOpen[card.getRow()][card.getColumn()] = true;
//Remember the index
Main.setIndex(Main.indexArray[card.getRow()][card.getColumn()]);
System.out.println("index: "+Main.getIndex());

//We opened the second card
}else if (Main.getIndex() != 0) {

//Check if it is a pair
if (Main.getIndex() == Main.indexArray[card.getRow()][card.getColumn()]) {

//Decrement the number of pairs
Main.pairs--;
//Open the second card
Main.isOpen[card.getRow()][card.getColumn()] = true;
//Reset the index
Main.resetIndex();

}else{ //Close both cards if it isn't a pair
//Wait 0.7 second to let the player remember the cards
try {
Thread.sleep(700);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Close the current card
card.closeCard();
System.out.println("index : " + Main.indexArray[card.getRow()][card.getColumn()]);
Main.isOpen[card.getRow()][card.getColumn()] = false;
//Close the first opened card by looking at the index
//It closes both cards with the same index, but it doesn't matter
//as the pair hasn't been found anyway
for (int i = 0; i < Main.indexArray.length; i++) {
for (int j = 0; j < Main.indexArray[0].length; j++) {
if (Main.getIndex() == Main.indexArray[i][j]) {
Main.cardArray[i][j].closeCard();
System.out.println("index: " + Main.indexArray[i][j]);
Main.isOpen[i][j] = false;
}
}
}
//Reset the index of last opened card
Main.resetIndex();
}
}
}

//Check endgame
if (Main.pairs == 0) {
//Show a dialog box
Alert incorrectPairs = new Alert(AlertType.INFORMATION);
incorrectPairs.setTitle("GAME OVER");
incorrectPairs.setHeaderText("The game is over");
incorrectPairs.setContentText("You found all the pairs, congrats!");
incorrectPairs.showAndWait();
}
}
//-------------------------------------------------
}

最佳答案

您正在使用 Thread.sleep(...) 阻止 UI 线程。这可以防止重新绘制任何挂起的更改,因此您根本看不到第一个更新;您只能在暂停完成后看到后续更新。

在 UI 线程上实现暂停的最简单方法是使用 PauseTransition来自 JavaFX 动画 API。基本上,你会的

PauseTransition pause = new PauseTransition(Duration.millis(700));
pause.setOnFinished(e -> {
// code to execute after pause...
});
pause.play();

就您而言,您可能希望禁用用户界面,以便用户在暂停期间无法单击任何内容,因此您可以执行类似的操作

PauseTransition pause = new PauseTransition(Duration.millis(700));
pause.setOnFinished(e -> {
card.closeCard();

// ... etc...

card.getParent().setDisable(false);
});

card.getParent().setDisable(true);
pause.play();

关于JavaFX : Button never sets a graphic,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30922241/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com