gpt4 book ai didi

java - repaint() 不会在调用时重新绘制?

转载 作者:行者123 更新时间:2023-12-02 04:40:54 27 4
gpt4 key购买 nike

我正在尝试制作一款三消游戏。我试图为实际发生的情况创建一些视觉辅助,首先将需要删除的 gem 标记为“黑色”,然后让重力完成它的工作。我正在努力做到这一点,在将它们标记为“黑色”后,我调用了 repaint(); ,但它似乎不起作用。我还尝试按照另一个问题中的建议添加 revalidate(); 但这似乎也无法解决问题。这是令我困扰的代码片段。

问题代码:

public void deletePattern(Set<Gem> gemsToDelete){
for(Gem gem : gemsToDelete)
gem.setType(7);

repaint(); //This doesn't seem to work

doGravity();
switchedBack = true;
checkPattern();
}

我想在 doGravity() 之前和增强的 for 循环之后重新绘制棋盘。难道是我在doGravity()方法中没有正确使用线程?

这是完整的代码:

Board.java

package Game;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedHashSet;
import java.util.Set;

public class Board extends JPanel{

final int BOARDWIDTH = 8;
final int BOARDHEIGHT = 8;

private static final Color COLORS[] = { new Color(255, 0, 0), new Color(255, 128, 0), new Color(255, 255, 0), new Color(0, 255, 0), new Color(0, 255, 255), new Color(0, 0, 255), new Color(127, 0, 255), new Color(0, 0, 0), new Color(0, 0, 0), new Color(255, 255, 255)};

boolean isAlive, isPattern, switchedBack;
boolean isFirstSelected = false;
Gem[][] gems;
int fromX, fromY, toX, toY;

public Board() {
gems = new Gem[BOARDWIDTH][BOARDHEIGHT];
addMouseListener(new MouseInputAdapter());
}

int cellWidth() { return (int) getSize().getWidth() / BOARDWIDTH; }

int cellHeight() { return (int) getSize().getHeight() / BOARDHEIGHT; }

public void start(){
isPattern = switchedBack = false;
isAlive = true;
fillBoard();
checkPattern();
switchedBack = false;
}

public void paint(Graphics g) {
super.paint(g);

for (int x = 0; x < BOARDWIDTH; x++) {
for (int y = 0; y < BOARDHEIGHT; y++)
drawCell(g, x, y, gems[x][y]);
}
}

public void fillBoard(){
for (int x = 0; x < BOARDWIDTH; x++) {
for (int y = 0; y < BOARDHEIGHT; y++)
gems[x][y] = new Gem();
}
}

public void drawCell(Graphics g, int x, int y, Gem gem) {
x = x * cellWidth();
y = y * cellHeight();

g.setColor(COLORS[gem.getType()]);
g.fillRect(x, y, x + cellWidth(), y + cellHeight());
}

class MouseInputAdapter extends MouseAdapter { @Override public void mouseClicked(MouseEvent e) { selectGems(e); } }

public void selectGems(MouseEvent e){
int x = e.getX() / cellWidth();
int y = e.getY() / cellHeight();
if(!isFirstSelected) {
fromX = x;
fromY = y;
isFirstSelected = true;
}else{
toX = x;
toY = y;
if((Math.abs(fromX - toX) == 1 ^ Math.abs(fromY - toY) == 1) & (gems[fromX][fromY].getType() != gems[toX][toY].getType())) {
switchGems();
isFirstSelected = false;
}
}

}

public void switchGems(){
int tempType = gems[fromX][fromY].getType();
gems[fromX][fromY].setType(gems[toX][toY].getType());
gems[toX][toY].setType(tempType);
checkPattern();

switchedBack = false;
repaint();
}

public void checkPattern() {
Set<Gem> gemsToDelete = new LinkedHashSet<>();

isPattern = false;
for (int x = 0; x < BOARDWIDTH; x++) {
for (int y = 0; y < BOARDHEIGHT; y++) {
if (x + 2 < BOARDWIDTH && (gems[x][y].getType() == gems[x + 1][y].getType()) && (gems[x + 1][y].getType() == gems[x + 2][y].getType())) { //Checks for 3 horizontal gems in a row
isPattern = true;
gemsToDelete.add(gems[x][y]);
gemsToDelete.add(gems[x + 1][y]);
gemsToDelete.add(gems[x + 2][y]);
}
if (y + 2 < BOARDHEIGHT && (gems[x][y].getType() == gems[x][y + 1].getType()) && (gems[x][y + 1].getType() == gems[x][y + 2].getType())) { //Check for 3 vertical gems in a row
isPattern = true;
gemsToDelete.add(gems[x][y]);
gemsToDelete.add(gems[x][y + 1]);
gemsToDelete.add(gems[x][y + 2]);
}
}
}
if(!gemsToDelete.isEmpty())
deletePattern(gemsToDelete);

if(!isPattern && !switchedBack){
switchedBack = true;
switchGems();
}
}

public void deletePattern(Set<Gem> gemsToDelete){
for(Gem gem : gemsToDelete)
gem.setType(7);

repaint(); //This doesn't seem to work

doGravity();
switchedBack = true;
checkPattern();
}

public void doGravity(){
try{
Thread.sleep(1000);
}catch(InterruptedException e){e.printStackTrace();}
for (int y = 0; y < BOARDHEIGHT; y++) {
for (int x = 0; x < BOARDWIDTH; x++) {
if(gems[x][y].getType() == 7){
for (int i = y; i >= 0; i--) {
if(i == 0)
gems[x][i].setType(gems[x][i].genType());
else
gems[x][i].setType(gems[x][i-1].getType());
}
}
}
}
}
}

Gem.java

package Game;

public class Gem {

private int type;

public Gem(){
this.type = genType();
}

public int genType(){
return (int) (Math.random() * 7);
}

public void setType(int type){
this.type = type;
}

public int getType(){
return type;
}
}

Game.java

package Game;

import javax.swing.*;

public class Game extends JFrame{

public Game(){
Board board = new Board();
getContentPane().add(board);
board.start();

setTitle("Game");
setSize(600, 600);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}

public static void main(String[] args){
Game game = new Game();
game.setLocationRelativeTo(null);
game.setVisible(true);
}
}

最佳答案

您的代码是通过单击鼠标启动的。从 Swing 监听器调用的代码在事件调度线程 (EDT) 上执行,该线程还负责绘制 GUI

doGravaity() 方法中的 Thread.sleep() 会导致 EDT hibernate ,因此 GUI 无法 repaint() 本身,直到整个循环代码完成已完成,此时它将仅绘制动画的最终状态。

您需要使用 Swing Timer 而不是 sleep 。安排动画。所以基本上,在 deletePattern() 方法中,您将启动计时器来执行重力动画。这将释放 EDT 来重新绘制自身,当计时器触发时,您将为组件设置动画一次,然后再次执行 repaint() 。当组件完成移动后,您将停止计时器。

阅读 Swing 教程中关于 Concurrency 的部分了解有关EDT的更多信息。

关于java - repaint() 不会在调用时重新绘制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30217832/

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