假设我有一张图片。我将图像放在JPanel中,并在JFrame中添加JPanel。图像从框架的底部移动到框架的顶部,同时使用AffineTransform
减小尺寸。变量使用线程更改。
所以这是以下代码:
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
功能(只是从下到上移动),图像会显示并移动但框架会快速闪烁(闪烁)。
任何想法都可以解决这个问题,这样我就可以在减小尺寸的同时移动图像并解决闪烁/快速闪烁的帧?
答案 0 :(得分:2)
您不应该覆盖JFrame的paint
方法。如果你想绘制任何东西,你应该在扩展JPanel
的类中绘制它,在那里覆盖paintComponent
方法。
您不应该在绘画方法中加载图像。这非常低效。您应该只在ONCE中加载图像,可能在构造函数中。
你不应该致电Graphics2D#setTransform()
。查看http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html#setTransform%28java.awt.geom.AffineTransform%29上的JavaDoc,它明确说明了
警告:此方法永远不会用于在现有转换的基础上应用新的坐标转换
您应该考虑w
和h
值。它们应该是绘制的图像的大小,还是用作图像的缩放因子?将它们设置为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);
}
}
答案 1 :(得分:2)
JFrame
等顶级容器上绘画。而是使用JPanel
并覆盖其paintComponent
方法并调用super.paintComponent
javax.swing.Timer
。new ImageIcon
方法中创建paint
。每次调用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的内容,但修复了你的其他问题。