repaint()没有重新打电话?

时间:2015-05-13 14:27:41

标签: java multithreading swing paint repaint

我试图打3场比赛。我试图通过首先标记需要删除的宝石"黑色"以及之后让重力去做它的工作来为实际发生的事情创建一些视觉辅助。我努力做到这一点,在我标记它们之后我打电话给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);
    }
}

2 个答案:

答案 0 :(得分:3)

通过鼠标单击启动您的代码。从Swing侦听器调用的代码在Event Dispatch Thread (EDT)上执行,Thread.sleep()也负责绘制GUI

doGravaity()方法中的deletePattern()会导致EDT进入睡眠状态,因此在整个循环代码完成之前,GUI无法重绘(),此时它只会绘制最终的动画的状态。

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

阅读Concurrency上Swing教程中的部分,了解有关mysqldump -h rds.host.name -u remote_user_name -p remote_db > dump.sql 的更多信息。

答案 1 :(得分:-1)

调用this.invalidate()this.postInvalidate()然后强制重新粉饰。