首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

请大神见见,JFrame的双缓冲

2014-01-22 
请大神看看,JFrame的双缓冲不是说swing有双缓冲么,为什么这样不行啊画的方块移动后是这个样子的public cla

请大神看看,JFrame的双缓冲
不是说swing有双缓冲么,为什么这样不行啊
画的方块移动后是这个样子的
请大神见见,JFrame的双缓冲


public class MainFrame extends JFrame implements KeyListener{

int x = 0;
int y = 0;

public void paint(Graphics g){
g.setColor(Color.red);
g.drawRect(x, y, 40, 30);
}

public void update(Graphics g) {

paint(g);

}

public void LunchFrame(){
this.setResizable(false);
this.setSize(512, 600);
this.setBackground(Color.black);
this.setTitle("飞机大战暴爽版!       xsx");
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
this.setVisible(true);
this.addKeyListener(this);

new Thread(new PaintThread()).start();
}

public static void main(String[] args){
MainFrame mframe = new MainFrame();
mframe.LunchFrame();
}

private class PaintThread implements Runnable {

public void run() {
while(true) {
repaint();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub

}

@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
 int keyCode = e.getKeyCode();
        //后面会添加具体按键匹配
        switch (keyCode) {
        case KeyEvent.VK_SPACE:
        
        break;
        case KeyEvent.VK_A:
        System.out.println("xxsx");
        x -= 1;
        break;
        case KeyEvent.VK_D:
        x += 1;
        break;
        case KeyEvent.VK_W:
        y -= 1;
        break;
        case  KeyEvent.VK_S:
        y += 1;
        break;
        }
}

@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub

}
}

[解决办法]
Double-buffering主要是动画时防止闪烁(因为image被缓存到off-screen了)
[解决办法]
不要直接重写JFrame的paint方法。
你应该使用JPanel,然后重写它的paintComponent(Graphics g)方法。
paintComponent第一行你需要调用父类的paintComponent方法,它会进行擦除,否则会有残影,你可以去掉试试。
然后你的update方法目前看起来是可以不用写的。无用代码。
下面给出修改后代码,直接粘贴可以运行


import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class MainPanel extends JPanel implements KeyListener {

private static final longserialVersionUID= 1147736728548400926L;

intx= 0;
inty= 0;

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.drawRect(x, y, 40, 30);
}

public static void main(String[] args) {
JFrame f = new JFrame();
MainPanel mPanel = new MainPanel();
f.add(mPanel);

f.setResizable(false);
f.setSize(512, 600);
f.setBackground(Color.black);
f.setTitle("飞机大战暴爽版!       xsx");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setVisible(true);

mPanel.addKeyListener(mPanel);
mPanel.start();
mPanel.requestFocus();


}

private void start() {
new Thread(new PaintThread()).start();
}

private class PaintThread implements Runnable {
public void run() {
while (true) {
repaint();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

@Override
public void keyTyped(KeyEvent e) {
}

@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
switch (keyCode) {
case KeyEvent.VK_SPACE:
break;
case KeyEvent.VK_A:
System.out.println("xxsx");
x -= 1;
break;
case KeyEvent.VK_D:
x += 1;
break;
case KeyEvent.VK_W:
y -= 1;
break;
case KeyEvent.VK_S:
y += 1;
break;
}
}

@Override
public void keyReleased(KeyEvent e) {
}
}


请大神见见,JFrame的双缓冲

[解决办法]

感谢指点,我之前也是把要画的东西继承JLabel或者JPanel,但是后来发现,那个在控制上不方便,比如要创建很多子弹,如果都添加在JPanel上好像不太好做,现在我重写了JFrame,把所有要画的东西直接画上去,好像很灵活

只是把之前的JFrame换成JPanel而已。子弹不需要继承JLabel。依然可以使用你现在“直接画上去”的思路。也就是,现在JPanel是画板,上面可以画子弹,画飞机……

其实你在JPanel的paintComponent里面这样写:

protected void paintComponent(Graphics g) {
super.paintComponent(g);
//绘制天空背景
//绘制飞机
//绘制子弹
//绘制UI
                //...
}

这样就可以了。

而你其实自己也可以定义一个绘制接口。比如:

public interface IDrawable{
    public void paint(Graphics g);
}


然后你那个自定义的画板JPanel里面包含一个绘制对象的列表,以及修改paintComponent的方法如下:

public class MainPanel extends JPanel implements KeyListener {

private static final List<IDrawable> drawableList = new LinkList<IDrawable>();

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for(IDrawable drawable : drawableList){
    drawable.paint(g);
                }
}
}

这个类上面其它代码就不重复贴了。
注意,这样是按顺序绘制panel中的IDrawable对象。因此,加对象进入drawableList时。你可能需要根据自己的逻辑进行排序。list的顺序会影响对象的覆盖顺序。



然后你的飞机就可以是这样啦:


public class AirPlane implements IDrawable {
        private int x;
        private int y;
@Override
public void paint(Graphics g) {
g.setColor(Color.RED);
                g.drawRect(x, y, 40, 30);
}
}

这样你只要把AirPlane加入MainPanel的drawableList里面就会绘制它了。

热点排行