0 0

JPanel中通过鼠标点击事件删除点中的组件为什么要repaint()后才能看到更新5

最近学习java图形的时候,准备写个打砖块的游戏练手,但是遇到很多问题。
请帮忙看看以下代码,RedBrick是一个红色的砖块,它需要被添加到一个游戏窗体BrickFrame中。BrickFrame添加了鼠标监听事件,测试代码时,我在事件中进行以下处理:删除通过鼠标点中的RedBrick。

import java.awt.*;

import javax.swing.*;
import javax.swing.border.*;

public class RedBrick extends JPanel {

        
        // 砖块的长和宽,常量
        public static final int WIDTH = 50;
        public static final int HEIGHT = 20;
        
        //常量名以颜色命名,值为颜色对应被销毁需要的次数
        public static final int RED = 1;
        public static final int ORANGE = 2;
        public static final int YELLOW = 3;
        public static final int GREEN = 4;
        public static final int CYAN = 5;
        public static final int BLUE = 6;
        public static final int MAGENTA = 7;
        
        //砖块在整个砖块方阵中所处的排数
        private int row;
        //砖块在整个砖块方阵中所处的列数
        private int column;
        
        //砖块的坐标
        private int x;
        private int y;
        
        private int color;
        //填充色,与变量color对应,通过方法getColor(color)来得到fillColor
        private Color fillColor;
        //边的颜色
        private Color edgeColor;


        public RedBrick(int row, int column){
this(RED, row, column);
        }
        
public RedBrick(int color, int row, int column){
                this.color = color;
                setFillColor(this.color);
                setBorder(new LineBorder(Color.BLUE));

                this.row = row;
                this.column = column;
                x = BrickFrame.START_X + WIDTH * column;
                y = BrickFrame.START_Y + HEIGHT * row;
        }

        /**
         * 设置砖块颜色
         * @param color 
         */
        private void setFillColor(int color) {
                fillColor = getColor(color);
        }
        
        
        /**
         * 通过该类中的颜色常量RED,ORANGE,YELLOW,GREEN,CYAN,BLUE,MAGENTA对应的Color类中的颜色,如果不为以上7种颜色,则返回Color.BLACK
         */
        private Color getColor(int color) {
                switch(color) {
                case RED: return Color.RED;
                case ORANGE: return Color.ORANGE;
                case YELLOW: return Color.YELLOW;
                case GREEN: return Color.GREEN;
                case CYAN: return Color.CYAN;
                case BLUE: return Color.BLUE;
                case MAGENTA: return Color.MAGENTA;
                default: return Color.BLACK;
                }
        }
        
        public void paintComponent(Graphics g){
                super.paintComponent(g);
                g.setColor(fillColor);
                g.fillRect(0, 0, WIDTH, HEIGHT);
                this.setLocation(x, y);
                this.setSize(WIDTH, HEIGHT);  //如果不设置size,一个Brick就会把整个Frame占满
        }

}

 

import java.awt.*;
import java.awt.event.*;
import java.util.*;

import javax.swing.*;

public class BrickFrame extends JPanel {
        private ArrayList<Brick> bricks = new ArrayList<Brick>(); //

        // 窗体的宽和高
        public final static int FRAME_WIDTH = 800;
        public final static int FRAME_HEIGHT = 600;

        // 砖块的起始坐标
        public final static int START_X = 0;
        public final static int START_Y = 60;

        private MouseAdapter mouseListener = new MouseAdapter() {

                public void mouseClicked(final MouseEvent e) {

                        remove(getComponentAt(e.getPoint()));
                        repaint(); //如果不调用repaint()方法,组件删除后不能马上看到效果,为什么?

                }
        };

        /**
         * 重写add方法,如果c是Brick类的一个实例,则将其转换为Brick类型然后添加到bricks中
         */
        public Component add(Component c) {
                super.add(c);
                if (c instanceof Brick) {
                        bricks.add((Brick) c);
                }
                return c;
        }

        /**
         * 重写add方法,如果c是Brick类的一个实例,则将其从bricks中删除
         */
        public void remove(Component c) {
                super.remove(c);
                if (c instanceof Brick) {
                        bricks.remove((Brick) c);
                }
        }

        public BrickFrame() {
                this.addMouseListener(mouseListener);
                this.addMouseMotionListener(mouseMotionListener);
        }

}

 下面是初始化代码

public class Test {
        public static void main(String[] args) {
                final JFrame jf = new JFrame(); 
                BrickFrame bf = new BrickFrame();
                
                //在窗体中添加Brick,
                for (int i = 0; i < 400 / Brick.HEIGHT; i++) {
                        for (int j = 0; j <(BrickFrame.FRAME_WIDTH - BrickFrame.START_X) / Brick.WIDTH; j++) {
                                bf.add(new RedBrick(i, j));
                        }
                }
                
                //下面代码放在for循环后,为什么?是不是for循环也要加入到EDT中?
                jf.add(bf);
                SwingUtilities.invokeLater(new Runnable() {
                        
                        public void run() {
                                jf.setTitle("打砖块");
                                jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                                jf.setSize(816, 638);
                                jf.setVisible(true);
                        }
                });
        }
}

 在鼠标监听事件中通过remove来删除鼠标点中的组件RedBrick

remove(getComponentAt(e.getPoint()));
但是如果不调用repaint()则不会马上看到砖块删除,需要改变窗体大小后才能看到。
我知道swing有个事件派发线程,但是还是不太明白为什么。

2014年3月18日 09:49

1个答案 按时间排序 按投票排序

0 0

repaint(),首先你得了解是在什么样的情况下会产生窗口重画。另外,我觉得最无语的是为什么都是组件来当一个砖头,你不觉得太夸张了吗。。。。请使用Graphics2D去完成。

2014年3月18日 10:50

相关推荐

Global site tag (gtag.js) - Google Analytics