透明背景清洁屏幕java

时间:2016-06-08 17:31:17

标签: java graphics paintcomponent repaint

我不确定这个问题是否与其他人有关,但我正在做一些简单的动画事情。我试图拥有一个透明的背景,使用以下代码很容易做到:

jf.setBackground(new Color(0,0,0,0));

问题在于,每当我试图移动的东西移动时(在我的情况下是一个史莱克图片),它就会不断地绘制并且不会清除之前的碎片。我会在下面发布所有代码。

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.io.*;
import java.util.logging.*;
import java.util.logging.*;
import javax.imageio.*;

public class MoveTest extends JPanel implements KeyListener {

  double velX = 0;
  double velY = 0;
  double moveX = 0;
  double moveY = 0;

  double posX = 1;
  double posY = 1;

  double friction = 1.005;

  BufferedImage image;

  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    try{                
      image = ImageIO.read(new File("shrek.png"));
    }catch (IOException ex){
      System.out.println("Image Does Not Exist");
    }

    g.setColor(Color.RED);
    moveX += velX;
    moveY += velY;

    posX += moveX;
    posY += moveY;
    g.drawImage(image,(int)posX,(int)posY,null);
  }

  public void keyPressed(KeyEvent e){
    int key = e.getKeyCode();

    int up = KeyEvent.VK_UP, w = KeyEvent.VK_W;
    int down = KeyEvent.VK_DOWN, s = KeyEvent.VK_S;
    int left = KeyEvent.VK_LEFT, a = KeyEvent.VK_A;
    int right = KeyEvent.VK_RIGHT, d = KeyEvent.VK_D;

    if(key == w || key == up)
      velY = -.2;
    if(key == s || key == down)
      velY = .2;
    if(key == a || key == left)
      velX = -.2;
    if(key == d || key == right)
      velX = .2;
  }

  public void keyReleased(KeyEvent e){
    int key = e.getKeyCode();

    int up = KeyEvent.VK_UP, w = KeyEvent.VK_W;
    int down = KeyEvent.VK_DOWN, s = KeyEvent.VK_S;
    int left = KeyEvent.VK_LEFT, a = KeyEvent.VK_A;
    int right = KeyEvent.VK_RIGHT, d = KeyEvent.VK_D;

    if(key == w || key == up)
      velY = 0;
    if(key == s || key == down)
      velY = 0;
    if(key == a || key == left)
      velX = 0;
    if(key == d || key == right)
      velX = 0;
  }

  public void keyTyped(KeyEvent e){}

  public static void main(String[] args) {
    MoveTest mt = new MoveTest();
    JFrame jf = new JFrame();

    jf.setTitle("Test one cladss");
    jf.setSize(1440,900);
    jf.setBackground(new Color(0,0,0,0));
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jf.add(mt);
    jf.setVisible(true);

    mt.setOpaque(true);
    mt.addKeyListener(mt);
    mt.requestFocusInWindow();

    while(true){
      //jf.removeAll();
      jf.repaint();

      mt.collision();
      mt.friction();
      try {
        Thread.sleep(16);
      } catch(InterruptedException ex) {
        Thread.currentThread().interrupt();
      }
    }
  }

  public void collision(){
    if(posX >= 1440-50|| posX <= 0){
      velX -= (2*velX);
      moveX -= (2*moveX);
    }
    if(posY >= 900-50 || posY <= 0){
      velY -= (2*velY);
      moveY -= (2*moveY);
    }
  }

  public void friction(){
    moveX /= friction;
    moveY /= friction;
  }
}

如果您有任何其他信息,请发表评论。任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:1)

我之前遇到过这种情况。从JFrame覆盖的paintComponent方法与覆盖所有其他组件的方法不同。由于您已经覆盖了JFrame的绘图代码,因此它不再删除背景。有两种解决方案:

  1. 添加您自己的JComponent(JPanel可以正常工作)并覆盖它的绘制方法而不是JFrame。
    1. 在调用super.paintComponent之后,首先自己清除画布。
    2. 另外:

      每次画画时都不应该阅读你的图像。由于在从任何线程调用重绘后很快就会进行绘制,因此图像可能会加载很多次。如果需要加载一次,请在类中创建一个无名实例块,如下所示:

      {
        try{                
          image = ImageIO.read(new File("shrek.png"));
        }catch (IOException ex){
          System.out.println("Image Does Not Exist");
        }
      }
      

      如果您只需要一份副本,请将其设为静态块:

      static {
         <load image here>
      }
      

      如果您想每帧重新加载图像,因为它会发生变化,您需要找到一种不这样做的方法。相反,任何图像动画都应该通过在java中编辑BufferImage对象或加载精灵图来实现。