单击 myButton 后,运行 2 个线程。首先更改按钮图像,第二个 - 循环。我希望我的程序首先更改图像并在运行循环之后。但这不行,一瞬间就完蛋了。
myButton.setOnMouseClicked(event -> {
if (event.getButton() == MouseButton.PRIMARY) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
ImageView imageView = new ImageView(image);
imageView.setFitHeight(my_button_height - 16);
imageView.setFitWidth(my_button_width - 16);
myButton.setStyle("-fx-background-color: #ffffff00; ");
myButton.setGraphic(imageView);
}
});
thread.run();
try {
thread.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 15; i++){
System.out.println(i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});
thread1.run();
}
});
}
我尝试添加.join。没有帮助
您不需要使用线程来实现您的需求。
游戏,在哪里找到与图像相同的卡片。卡片是带有图像的按钮。当玩家打开两张牌时,我的程序会检查它们,如果它们相同,则一切都很好,以另一种方式关闭。但是当玩家打开第二张牌时我遇到了一个问题,他看不到它
问题在于,在某些情况下,玩家行动后没有暂停,因此玩家在翻回之前无法看到他们翻过的牌。
这可以使用
PauseTransition
来修复。这个答案解释了用法:
示例
这里是一些记忆游戏的示例代码。例子:
这只是一个演示应用程序,它没有经过彻底的测试,并且可能存在一些错误,但希望它说明了一种使用 PauseTransition 概念来解决与您遇到的问题类似的问题的方法。
MemoryGame.java
import javafx.animation.PauseTransition;
import javafx.beans.Observable;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.collections.*;
import javafx.collections.transformation.FilteredList;
import javafx.geometry.Insets;
import javafx.scene.control.Labeled;
import javafx.scene.layout.Pane;
import javafx.scene.layout.TilePane;
import javafx.util.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class MemoryGame {
private static final Duration FLIP_PAUSE_DURATION = Duration.seconds(
1
);
private final TilePane board;
private final ReadOnlyBooleanWrapper solved = new ReadOnlyBooleanWrapper(
false
);
public MemoryGame(String tileText) {
ObservableList<Tile> tiles = createTiles(tileText);
FilteredList<Tile> visibleTiles = tiles.filtered(Tile::isShowing);
board = createBoard(tiles);
PauseTransition pauseForCompletion = new PauseTransition(
FLIP_PAUSE_DURATION
);
pauseForCompletion.setOnFinished(e ->
completeMove(tiles, visibleTiles, board)
);
visibleTiles.addListener((ListChangeListener<Tile>) c ->
respondToMove(visibleTiles, board, pauseForCompletion)
);
}
private static void respondToMove(
FilteredList<Tile> visibleTiles,
TilePane board,
PauseTransition pauseForCompletion
) {
if (visibleTiles.size() == 2) {
board.setDisable(true);
pauseForCompletion.playFromStart();
}
}
private void completeMove(
ObservableList<Tile> tiles,
FilteredList<Tile> visibleTiles,
TilePane board
) {
long nShowing = visibleTiles.stream()
.map(Labeled::getText)
.distinct()
.count();
if (nShowing == 1) { // all visible tiles match
// replace all matching tiles with a blank pane.
for (Tile tile : visibleTiles) {
int tileIdx = board.getChildren().indexOf(tile);
board.getChildren().set(tileIdx, new Pane());
}
for (int i = visibleTiles.size() - 1; i >= 0; i--) {
tiles.remove(visibleTiles.get(i));
}
if (tiles.isEmpty()) {
solved.set(true);
}
} else {
// tiles don't match, so hide them until they are turned again.
for (int i = visibleTiles.size() - 1; i >= 0; i--) {
visibleTiles.get(i).setShowing(false);
}
}
board.setDisable(false);
}
private static TilePane createBoard(ObservableList<Tile> tiles) {
TilePane board = new TilePane(
10, 10
);
board.getStyleClass().add("board");
board.getChildren().addAll(tiles);
board.setPrefColumns((int) Math.sqrt(tiles.size()));
board.setPadding(new Insets(10));
return board;
}
private static ObservableList<Tile> createTiles(String tileText) {
List<String> gameText =
(tileText + tileText)
.chars()
.mapToObj(Character::toString)
.collect(Collectors.toCollection(ArrayList::new));
Collections.shuffle(gameText);
ObservableList<Tile> tiles = FXCollections.observableArrayList(
tile -> new Observable[] { tile.showingProperty() }
);
gameText.stream()
.map(Tile::new)
.forEachOrdered(tiles::add);
return tiles;
}
public TilePane getBoard() {
return board;
}
public boolean isSolved() {
return solved.get();
}
public ReadOnlyBooleanProperty solvedProperty() {
return solved.getReadOnlyProperty();
}
}
Tile.java
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.control.Button;
class Tile extends Button {
private static final String BLANK = " ";
private final BooleanProperty showing = new SimpleBooleanProperty(
false
);
public Tile(String tileText) {
getStyleClass().add("tile");
textProperty().bind(
Bindings
.when(showing)
.then(tileText)
.otherwise(BLANK)
);
setOnAction(e -> setShowing(true));
}
public boolean isShowing() {
return showing.get();
}
public BooleanProperty showingProperty() {
return showing;
}
public void setShowing(boolean showing) {
this.showing.set(showing);
}
}
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.control.Button;
class Tile extends Button {
private static final String BLANK = " ";
private final BooleanProperty showing = new SimpleBooleanProperty(
false
);
public Tile(String tileText) {
getStyleClass().add("tile");
textProperty().bind(
Bindings
.when(showing)
.then(tileText)
.otherwise(BLANK)
);
setOnAction(e -> setShowing(true));
}
public boolean isShowing() {
return showing.get();
}
public BooleanProperty showingProperty() {
return showing;
}
public void setShowing(boolean showing) {
this.showing.set(showing);
}
}
MemoryGameApp.java
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class MemoryGameApp extends Application {
private static final String TILE_TEXT = "Qn39Pzr#";
private static final String CSS =
"""
data:text/css,
.board .button:disabled {
-fx-opacity: 1;
}
.tile {
-fx-font-family: monospace; -fx-font-size: 40px;
}
""";
private MemoryGame memoryGame;
private Scene scene;
@Override
public void start(Stage stage) {
memoryGame = new MemoryGame(TILE_TEXT);
scene = new Scene(memoryGame.getBoard());
scene.getStylesheets().add(CSS);
stage.setScene(scene);
stage.show();
memoryGame.solvedProperty().addListener(new EndGameListener());
}
public static void main(String[] args) {
launch(args);
}
class EndGameListener implements ChangeListener<Boolean> {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (memoryGame.isSolved()) {
memoryGame.solvedProperty().removeListener(this);
memoryGame = new MemoryGame(TILE_TEXT);
memoryGame.solvedProperty().addListener(this);
scene.setRoot(memoryGame.getBoard());
}
}
}
}