简体   繁体   English

repaint()是否在调用时不重新绘制?

[英]repaint() doesn't repaint on call?

I'm trying to make a match 3 game. 我正在尝试进行第3场比赛。 I am trying to create some visual aid to what is actually happening by first marking the gems that need to be deleted "black", and after that letting gravity do it's job. 我试图通过先将需要删除的宝石标记为“黑色”,然后通过重力来完成工作,从而为实际发生的情况提供一些视觉辅助。 I'm struggling to do this, I called repaint(); 我正在努力做到这一点,我叫repaint(); after I marked them "black", but it doesn't seem to work. 在我将它们标记为“黑色”之后,但似乎不起作用。 I also tried adding in revalidate(); 我也尝试添加revalidate(); as suggested in another question but that doesn't seem to fix the problem either. 正如另一个问题中所建议的那样,但这似乎也无法解决问题。 Here's the piece of code that's troubling me. 这是令我困扰的代码。

Trouble code: 故障代码:

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

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

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

I want to repaint the board before doGravity() and after the enhanced for loop. 我想在doGravity()之前和增强的for循环之后重新绘制木板。 Could it be that I'm not using the thread correctly in the doGravity() method? 可能是我没有在doGravity()方法中正确使用线程吗?

Here's the full code: 这是完整的代码:

Board.java 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 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);
    }
}

Your code is initiated via a mouse click. 您的代码是通过鼠标单击启动的。 Code invoked from a Swing listener is executed on the Event Dispatch Thread (EDT) , which is also responsible for painting the GUI 从Swing侦听器调用的代码在Event Dispatch Thread (EDT)上执行,该Event Dispatch Thread (EDT)还负责绘制GUI

The Thread.sleep() in your doGravaity() method causes the EDT to sleep, therefore the GUI can't repaint() itself until the whole looping code is finished, at which point it will just paint the final state of your animation. doGravaity()方法中的Thread.sleep()会使EDT进入睡眠状态,因此,在整个循环代码完成之前,GUI不能重绘()自身,此时,它只会绘制动画的最终状态。

Instead of sleeping, you need to use a Swing Timer to schedule animation. 您需要使用Swing计时器来安排动画,而不是睡觉。 So basically, in the deletePattern() method you would start the Timer to do the gravity animation. 因此,基本上,在deletePattern()方法中,您将启动Timer进行重力动画。 This will free up the EDT to repaint itself and when the Timer fires you would animate your components one move and then do repaint() again. 这将释放EDT来重绘自身,并且当Timer触发时,您可以移动组件动画,然后再次执行repaint()。 When the components are finished moving you stop the timer. 组件移动完毕后,您将停止计时器。

Read the section from the Swing tutorial on Concurrency for more information about the EDT . 阅读Swing 并发教程中有关EDT更多信息。

调用this.invalidate()this.postInvalidate() ,然后强制重新绘制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM