2014-01-25 53 views
4

让我说我有一个图像。我把图像放在一个JPanel中,并在JFrame中添加JPanel。图像从框架底部移动到框架顶部,同时使用AffineTransform缩小其大小。该变量使用线程更改。通过线程缩放图像 - JAVA

所以这里的下面的代码:

public class SplashScreen extends JFrame{ 
    Image img1; 
    int w=1,h=1; 
    int x=0,y=0; 
    Thread th = new Thread(new Runnable() { 
    @Override 
    public void run() { 
     while(true){ 
      w-=0.05; 
      h-=0.05; 
      y-=2; 
      x+=1; 

      if(y==-100){ 
       new MainMenu_BlueJay().setVisible(true); 
       dispose(); 
      } 

      repaint(); 
      try { 
       Thread.sleep(10); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(SplashScreen.class.getName()).log(Level.SEVERE, null, ex); 
      } 

     } 
    } 
}); 

JPanel p = new JPanel(); 

public SplashScreen(){ 
    setLayout(new BorderLayout()); 

    p.setPreferredSize(new Dimension(900,600)); 
    p.setBackground(Color.black); 
    p.setLayout(new GridLayout()); 

    add(p); 
    setTitle("BlueJay"); 
    setSize(900,600); 

    getContentPane().setBackground(Color.black); 
    setDefaultCloseOperation(EXIT_ON_CLOSE); 
    setLocationRelativeTo(null); 
    setVisible(true); 
    th.start(); 
    requestFocus(); 
    setFocusable(true); 
} 

@Override 
public void paint(Graphics g) { 
    super.paint(g); 
    Graphics2D g2d = (Graphics2D) g; 

    img1 = new ImageIcon("images/Intro/BJ Production 2013.png").getImage(); 
    AffineTransform at = new AffineTransform(); 
    at.scale(w,h); 
    g2d.setTransform(at); 
    g2d.drawImage(img1, x, y, p); 
} 

public static void main(String[] args) { 
    new SplashScreen(); 
} 

但是我从代码获得以上只是黑屏。怎么了?无论如何,如果我不使用AffineTransform功能(只是从下往上移动),图像会显示并移动,但是框架会快速闪烁(闪烁)。

任何想法来解决这个问题,所以我可以移动图像,同时减小其大小,也解决了闪烁/快速闪烁帧?

+1

首先,你的变量线程访问应该是volatile的。其次,线程内部的paint调用必须与SwingUtilities.invokeLater() – morpheus05

+0

一起围绕。那么如果不使用线程,如何减少变量的值? – noobprogrammer

回答

2

您不应该覆盖JFrame的paint方法。如果你想画任何东西,你应该画一个延伸JPanel的类,在这里你覆盖paintComponent方法。

您不应该在绘画方法中加载图像。这是非常低效的。您应该只在一次构造函数中加载图像。

您不应该致电Graphics2D#setTransform()。看一看的JavaDoc在http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html#setTransform%28java.awt.geom.AffineTransform%29,其中明确规定

警告:此方法应从未用来申请一个新的坐标之上将现有变换

你应该想想你wh值。它们应该是大小的的图像,或者用作比例因子的图像?将它们设置为AffineTransform的缩放因子不会产生将图像缩放到所需大小的效果。目前,它们被声明为int的值,所以像w-=0.05这样的东西无论如何都没有意义。

您应该清楚如何描述图像应该执行的动画。

人可能总结一下:

你不应该写代码,并认为它是“正确的”,只是因为没有编译错误;-)

然而,下面的片段可能是第一步朝着自己的目标:

package stackoverflow; 

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Image; 

import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class SplashScreen extends JFrame 
{ 
    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       new SplashScreen(); 
      } 
     }); 
    }  

    private PaintPanel paintPanel; 

    public SplashScreen() 
    { 
     setTitle("BlueJay"); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 

     getContentPane().setBackground(Color.BLACK); 
     getContentPane().setLayout(new BorderLayout()); 

     paintPanel = new PaintPanel(); 
     getContentPane().add(paintPanel, BorderLayout.CENTER); 

     setSize(900,600); 
     setLocationRelativeTo(null); 
     setFocusable(true); 
     requestFocus(); 
     setVisible(true); 

     startAnimation(); 
    } 

    void startAnimation() 
    { 
     Thread thread = new Thread(new Runnable() 
     { 
      int x = 100; 
      int y = 100; 
      int w = 0; 
      int h = 0; 

      @Override 
      public void run() 
      { 
       try 
       { 
        Thread.sleep(500); 
       } 
       catch (InterruptedException ex) 
       { 
        Thread.currentThread().interrupt(); 
        return; 
       } 

       while (true) 
       { 
        if (y == 200) 
        { 
         // new MainMenu_BlueJay().setVisible(true); 
         dispose(); 
        } 

        x += 2; 
        y += 1; 
        w += 1; 
        h += 1; 
        paintPanel.setImageCoordinates(x, y, w, h); 

        repaint(); 
        try 
        { 
         Thread.sleep(10); 
        } 
        catch (InterruptedException ex) 
        { 
         Thread.currentThread().interrupt(); 
         return; 
        } 

       } 
      } 
     }); 
     thread.start(); 
    } 
} 


class PaintPanel extends JPanel 
{ 
    private final Image image; 
    private int imageX, imageY; 
    private int imageW, imageH; 

    PaintPanel() 
    { 
     image = new ImageIcon("Clipboard02.jpg").getImage(); 
     imageX = 0; 
     imageY = 0; 
     imageW = 0; 
     imageH = 0; 
    } 

    void setImageCoordinates(int imageX, int imageY, int imageW, int imageH) 
    { 
     this.imageX = imageX; 
     this.imageY = imageY; 
     this.imageW = imageW; 
     this.imageH = imageH; 
     repaint(); 
    } 

    @Override 
    protected void paintComponent(Graphics gr) 
    { 
     super.paintComponent(gr); 
     Graphics2D g = (Graphics2D) gr; 

     float scalingX = (float) imageW/image.getWidth(null); 
     float scalingY = (float) imageH/image.getHeight(null); 
     g.scale(scalingX, scalingY); 

     int ix = (int)(imageX/scalingX); 
     int iy = (int)(imageY/scalingY); 
     g.drawImage(image, ix, iy, null); 
    } 
} 
2
  1. 不要在顶层容器烤漆工艺般JFrame。而是使用JPanel并覆盖其paintComponent方法并呼叫super.paintComponent
  2. 无需调用Thread.sleep()。请使用javax.swing.Timer
  3. 从EDT
  4. 运行程序不paint方法创建一个new ImageIcon。它会在每次调用repaint()时创建新的ImageIcon对象。相反,在构造函数中实例化它。

这里是代码的重构。

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

public class SplashScreen extends JFrame { 

    Image img1; 
    int w = 900, h = 600; 
    int x = 0, y = 0; 

    public SplashScreen() { 

     setLayout(new BorderLayout()); 

     add(new MyPanel()); 
     setTitle("BlueJay"); 
     setSize(900, 600); 

     getContentPane().setBackground(Color.black); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     setLocationRelativeTo(null); 
     setVisible(true); 

     requestFocus(); 
     setFocusable(true); 

    } 

    private class MyPanel extends JPanel { 

     public MyPanel() { 
      img1 = new ImageIcon(SplashScreen.class.getResource("/resources/stackoverflow5.png")).getImage(); 
      setBackground(Color.black); 
      setLayout(new GridLayout()); 
      Timer timer = new Timer(20, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        w -= 5; 
        h -= 5; 
        y -= 2; 
        x += 1; 

        if (y == -250) { 
         new MainMenu_BlueJay().setVisible(true); 
         dispose(); 
        } 
        repaint(); 
       } 
      }); 
      timer.start(); 
     } 

     @Override 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g; 

      //AffineTransform at = new AffineTransform(); 
      // at.scale(w, h); 
      // g2d.setTransform(at); 
      g2d.drawImage(img1, x, y, w, h, this); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(900, 600); 
     } 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new SplashScreen(); 
      } 
     }); 

    } 
} 

我不太熟悉Graphics2D,所以我评论了AffirmTransformation的东西,但解决了其他问题。