JPanel重绘不清除

时间:2011-09-12 16:51:38

标签: java swing jpanel repaint

我有一个自定义的抽象类'Panel',它扩展了JPanel。绘画时两者差别不大。我有一个Panel,我通过更新图像的x值来模拟动画。我现在有两个动画,一个适当重绘,另一个不重复。这是针对没有的。有效的那个将被标记为A,那个没有的将被标记为B.

A和B遵循相同的格式。更新Panel上的一些变量,调用update(Panel中调用PaintComponent的方法),然后调用repaint。它之后调用重绘,因为此问题之前是A并且以这种方式解决了。

答:更新图像变量。 B:更新图像的x变量。

问题:重绘不会清除旧的图像位置,因此屏幕上会出现乱码。

我尝试了什么:

  • 我看过super.PaintComponent(g)提到了很多,但是这个 还没有解决问题。
  • 我尝试更改重绘/更新方法的顺序 调用。
  • 重绘不会更新面板。 (可能是因为 绘画在PaintComponent中完成)

任何帮助都将不胜感激。

代码:

面板:

public Panel (boolean visible){
    super();
    this.setLayout(new BorderLayout(640, 416));//sets the Layout type of the panel
    this.setOpaque(false);//Makes it so that the panel underneath can be seen where images aren't drawn
    this.setVisible(visible);
    ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    gs = ge.getDefaultScreenDevice();
    gc = gs.getDefaultConfiguration();
}

public void paintComponent (Graphics g){
    setUp();
    drawOff();
    setDown(g);
}

private void setUp(){
    off_screen = gc.createCompatibleImage(getSize().width, getSize().height, Transparency.TRANSLUCENT);
    buffer = off_screen.createGraphics();
}

protected abstract void drawOff();

private void setDown(Graphics g){
    g.drawImage(off_screen,0,0,this);
    off_screen.flush(); 
}

public void update(){
    paintComponent(this.getGraphics());
}

动画方法(毫克是有问题的小组):

private void battleStart(User user) {
    for (int i = 0; i < user.battle.length; i++) {
        mg.battleStart(user.battleStart(i));
        mg.update();
        try {
            Thread.sleep(150);
        } catch (Exception e) {

        }
        mg.repaint();
    }
}

private void animateStart(User user){
    for (int i = 0; i < 10; i++){
        mg.x = mg.x + 10;
        mg.update();
        try {
            Thread.sleep(100);
        } catch (Exception e) {

        }
        mg.repaint();
    }
}

1 个答案:

答案 0 :(得分:3)

我认为你的设计已经过时了,这就是事情不起作用的原因。我不太确定你的非抽象JPanel是如何工作的,但是考虑让你的父JPanel更多地沿着这些方向发展:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class MyPanel extends JPanel {
   private GraphicsEnvironment ge;
   private GraphicsDevice gs;
   private GraphicsConfiguration gc;
   private BufferedImage offScreen;

   public MyPanel(boolean visible) {
      super();
      this.setLayout(new BorderLayout(640, 416)); // strange constants for this layout.
      this.setOpaque(false);
      this.setVisible(visible);
      ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
      gs = ge.getDefaultScreenDevice();
      gc = gs.getDefaultConfiguration();

      addComponentListener(new ComponentAdapter() {
         @Override
         public void componentResized(ComponentEvent e) {
            setUp();
         }
      });
   }

   @Override
   // don't make this public. Keep it protected like the super's
   // just draw in this method. Don't call other methods that create buffers
   // or draw to buffers.
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (offScreen != null) {
         g.drawImage(offScreen, 0, 0, null);
      }
   }

   private void setUp() {
      offScreen = gc.createCompatibleImage(getSize().width, getSize().height,
            Transparency.TRANSLUCENT);
   }

   // draw to the buffer outside of the paintComponent
   // and then call repaint() when done
   public void upDateOffScreen() {
      // ?? offScreen.flush(); // I've never used this before, 
                  // so am not sure if you need this here
      Graphics2D osGraphics = offScreen.createGraphics();
      // TODO: do drawing with osGraphics object here
      osGraphics.dispose();
      repaint();
   }
}

一次又一次,

  • 从EDT(事件调度线程)中删除所有长处理方法。
  • 永远不要在EDT上调用Thread.sleep(...)。
  • 考虑使用Swing Timers而不是使用Thread.sleep作为动画。
  • 可以在EDT上调用JPanel上的重绘,但大部分都是关于它的。
  • 应该在EDT上调用所有其他Swing方法。
  • 阅读,重读和研究2D和Swing图形教程。