使用 Java Swing 制作动画精灵

Ped*_*edo -1 java animation swing timer jpanel

有人可以告诉我如何减慢精灵的出现速度以创建更流畅的动画吗?当我运行代码时,它出现在 JPanel 中的最后一个(第 27 个)精灵。动画处理速度太快了!

有人告诉我有关 Swing Timer 的信息,但不幸的是我尝试了几次,但无法让代码运行良好:(

这是我到目前为止的代码:

package sprites;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Sprites extends JFrame {

public static void main(String[] args) {
    JFrame frm1 = new JFrame();
    frm1.setSize(400, 400);
    frm1.setLocationRelativeTo(null);
    frm1.setResizable(false);
    frm1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Painel1 pn1 = new Painel1();
    frm1.getContentPane().add(pn1);
    frm1.setVisible(true);
  }
}

class Painel1 extends JPanel {

    BufferedImage img;

    public Painel1() {
        setBackground(Color.yellow);
    try
    {
      img = ImageIO.read(new File("images/dummy.png"));
    }
    catch (IOException e)
    {}
  }

  @Override
  public void paintComponent(Graphics g) {
    int[][] spriteSheetCoords = {{8, 10, 119, 129}, 
                                 {138, 10, 118, 130},
                                 {267, 10, 118, 132},
                                 {402, 11, 113, 132},
                                 {538, 12, 106, 134},
                                 {671, 13, 103, 133},
                                 {804, 12, 102, 132},
                                 {23, 161, 100, 134},
                                 {157, 162, 96, 134},
                                 {287, 159, 95, 135},
                                 {418, 158, 95, 133},
                                 {545, 159, 99, 133},
                                 {673, 159, 102, 134},
                                 {798, 158, 108, 130},
                                 {9, 309, 116, 126},
                                 {137, 309, 118, 127},
                                 {274, 310, 110, 128},
                                 {412, 311, 102, 129},
                                 {541, 312, 103, 130},
                                 {671, 312, 104, 131},
                                 {806, 312, 98, 132},
                                 {29, 463, 94, 135},
                                 {155, 462, 98, 135},
                                 {279, 461, 104, 135},
                                 {409, 461, 106, 135},
                                 {536, 461, 109, 135},
                                 {662, 461, 112, 133}};
    Image subSprite;
    for (int i = 0; i <= 26; i++) {
      super.paintComponent(g);
      subSprite = img.getSubimage(spriteSheetCoords[i][0], spriteSheetCoords[i][1], spriteSheetCoords[i][2], spriteSheetCoords[i][3]);
      g.drawImage(subSprite, 140, 120, null);
    }
  }  
}
Run Code Online (Sandbox Code Playgroud)

假设创建一个从第一个精灵到最后一个(第 27 个)精灵的循环。

Fra*_*ool 5

  1. 首先,每行之间有很多空格,这使得阅读代码变得困难。

  2. 是的,您可以尝试使用 Swing Timer,这是一个示例、另一个示例和另一个示例

  3. 你有一个catch不安全的空块,至少这样做:

    catch (IOException e){
        e.printStackTrace();
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 您不会将程序放在事件调度线程(EDT)上来解决它,只需更改您的main方法,如下所示:

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                //Your constructor here
            }
        });
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. 您正在扩展JFrame但不使用它生成的框架,同时您正在创建 a 的实例JFrame,请删除extends JFrame代码中的 。相关阅读:Java Swing 使用扩展 JFrame 与在类内部调用它

  6. 而不是调用frm1.setSize(400, 400);overridePainel1getPreferredSize()方法来返回新Dimension400, 400并调用frm1.pack()

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(400, 400);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  7. 动画处理速度太快了!

    这并不是动画处理太快,而是for循环阻止了 GUI 在结束之前被绘制,这就是为什么您只能看到最后一个精灵被绘制的原因。


考虑到上述所有要点,您现在可以使用如下代码,其中包括 Swing Timer 的使用以及已包含的上述建议:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Sprites {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frm1 = new JFrame();
                Painel1 pn1 = new Painel1();
                frm1.getContentPane().add(pn1);

                frm1.pack();
                frm1.setVisible(true);
                frm1.setLocationRelativeTo(null);
                frm1.setResizable(false);
                frm1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            }
        });
    }
}

class Painel1 extends JPanel {

    int[][] spriteSheetCoords = { { 8, 10, 119, 129 }, { 138, 10, 118, 130 }, { 267, 10, 118, 132 },
            { 402, 11, 113, 132 }, { 538, 12, 106, 134 }, { 671, 13, 103, 133 }, { 804, 12, 102, 132 },
            { 23, 161, 100, 134 }, { 157, 162, 96, 134 }, { 287, 159, 95, 135 }, { 418, 158, 95, 133 },
            { 545, 159, 99, 133 }, { 673, 159, 102, 134 }, { 798, 158, 108, 130 }, { 9, 309, 116, 126 },
            { 137, 309, 118, 127 }, { 274, 310, 110, 128 }, { 412, 311, 102, 129 }, { 541, 312, 103, 130 },
            { 671, 312, 104, 131 }, { 806, 312, 98, 132 }, { 29, 463, 94, 135 }, { 155, 462, 98, 135 },
            { 279, 461, 104, 135 }, { 409, 461, 106, 135 }, { 536, 461, 109, 135 }, { 662, 461, 112, 133 } };

    int i = 0;
    BufferedImage img;

    private ActionListener actionListener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            i++;
            if (i == spriteSheetCoords.length) {
                i = 0;
            }
            revalidate();
            repaint();
        }
    };

    public Painel1() {
        Timer timer = new Timer(50, actionListener);
        timer.setInitialDelay(0);
        timer.start();
        setBackground(Color.yellow);
        try {
            img = ImageIO.read(new File("/home/jesus/Pictures/tokyo.jpg"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        Image subSprite;
        super.paintComponent(g);
        subSprite = img.getSubimage(spriteSheetCoords[i][0], spriteSheetCoords[i][1], spriteSheetCoords[i][2], spriteSheetCoords[i][3]);
        g.drawImage(subSprite, 140, 120, null);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(400, 400);
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

正如你所看到的,Timer有 50ms 的延迟,以使精灵的过渡更加平滑,你可以根据需要进行调整。

  • 对于投反对票的人来说,由于其他(质量较差)答案都没有被投反对票,并且该问题没有新的反对票或接近票,我们只能假设您对回答者有个人恩怨和/或实际上并不理解该问题答案,除非你愿意努力提供如何使答案更好的建议,否则什么都不会改变。如果问题存在问题,请对其投反对票和/或投票关闭它。请不要惩罚试图帮助别人的人 (2认同)