当前位置: 首页 > 知识库问答 >
问题:

Java动画JLabel

何涵育
2023-03-14

因此,我正在创建一个基本的应用程序,我希望在屏幕底部有一个JLabel,从左下角开始,在设定的时间内移动到右下角,动画风格,并在中心有一个静态图像。为此,我使用BorderLayout创建了一个带有JPanel的JFrame。在BorderLayout.Center中添加了一个带有ImageIcon的JLabel,在BorderLayout.South中添加了一个JPanel。我的代码虽然编写得很匆忙,也很不漂亮,但它是:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension; 
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.BorderFactory;

public class GameWindow extends JPanel{

private static JLabel mainWindow, arrowLabel, arrowBox;
protected static JFrame frame;
protected static JPanel arrows;

public static int x = 600;

public GameWindow(){
    mainWindow = new JLabel("Center");
    arrowLabel = new JLabel("Moving");
    arrows = new JPanel();
    arrows.setSize(600, 100);
    arrows.setLayout(null);
    arrowBox = new JLabel("");
    arrowBox.setBounds(0, 0, 150, 100);
    arrowBox.setPreferredSize(new Dimension(150, 100));
    arrowBox.setBorder(BorderFactory.createLineBorder(Color.black));
    arrows.add(arrowBox);
    this.setSize(600,600);
    this.setLayout(new BorderLayout());
    this.add(mainWindow, BorderLayout.CENTER);
    this.add(arrows, BorderLayout.SOUTH);
}

public static void main(String[] args)
{
    GameWindow g = new GameWindow();
    frame = new JFrame("Sword Sword Revolution");
    frame.add(g);
    frame.setSize(600,600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);

    Timer t = new Timer(1000, new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent e) {
            arrows.add(arrowLabel);
            arrowLabel.setBounds(x, 100, 100, 100);
            x-=50;
            arrows.repaint();
            frame.repaint();
        }

    });
    t.start();
}

共有1个答案

屠振濂
2023-03-14

对于Swing应用程序来说,线程的使用完全是错误的。您不应该尝试在后台线程中添加或删除组件,而应该使用Swing计时器在Swing事件线程上执行此操作。

还有,你说:

我想在屏幕底部有一个滚动的JLabel

为了澄清,我希望在屏幕底部的最右角有一个JLabel,然后在swing计时器中,JLabel将逐渐向左移动,直到它离开屏幕。如果我可以让setLocation工作,基本前提是将变量x设置为600,然后每秒将x减量50,然后在屏幕上的新位置重新绘制JLabel。基本动画。

我将为屏幕底部创建一个JPanel,用于保存JLabel或通过重写其PaintComponent(...)方法来显示不使用JLabel的图像。如果您将它用作容器,那么是的,它的布局应该是null,但是GUI的其余部分不应该使用null布局。Swing计时器只需更改JLabel的位置,然后在其JPanel/Container上调用repaint()。如果采用后一种方法,您将使用g.drawimage(myImage,x,y)在JPanel的PaintComponent(...)方法中绘制图像,定时器将更改x和/或y,并调用绘制JPanel的repaint()

另外,您可能不想一直在计时器中添加JLabel,而是简单地移动GUI中已经显示的JLabel。

编辑4
例如:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.EnumMap;

import javax.imageio.ImageIO;
import javax.swing.*;

@SuppressWarnings("serial")
public class AnimateExample extends JPanel {
   public static final String DUKE_IMG_PATH = 
         "https://duke.kenai.com/iconSized/duke.gif";
   private static final int PREF_W = 800;
   private static final int PREF_H = 800;
   private static final int TIMER_DELAY = 20;
   private static final String KEY_DOWN = "key down";
   private static final String KEY_RELEASE = "key release";
   public static final int TRANSLATE_SCALE = 3;
   private static final String BACKGROUND_STRING = "Use Arrow Keys to Move Image";
   private static final Font BG_STRING_FONT = new Font(Font.SANS_SERIF,
         Font.BOLD, 32);
   private EnumMap<Direction, Boolean> dirMap = 
         new EnumMap<AnimateExample.Direction, Boolean>(Direction.class);
   private BufferedImage image = null;
   private int imgX = 0;
   private int imgY = 0;
   private int bgStringX; 
   private int bgStringY; 

   public AnimateExample() {
      for (Direction dir : Direction.values()) {
         dirMap.put(dir, Boolean.FALSE);
      }
      try {
         URL imgUrl = new URL(DUKE_IMG_PATH);
         image = ImageIO.read(imgUrl);
      } catch (MalformedURLException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }

      new Timer(TIMER_DELAY, new TimerListener()).start();

      // here we set up our key bindings
      int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition);
      ActionMap actionMap = getActionMap();
      for (final Direction dir : Direction.values()) {

         // for the key down key stroke
         KeyStroke keyStroke = KeyStroke.getKeyStroke(dir.getKeyCode(), 0,
               false);
         inputMap.put(keyStroke, dir.name() + KEY_DOWN);
         actionMap.put(dir.name() + KEY_DOWN, new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
               dirMap.put(dir, true);
            }
         });

         // for the key release key stroke
         keyStroke = KeyStroke.getKeyStroke(dir.getKeyCode(), 0, true);
         inputMap.put(keyStroke, dir.name() + KEY_RELEASE);
         actionMap.put(dir.name() + KEY_RELEASE, new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
               dirMap.put(dir, false);
            }
         });
      }

      FontMetrics fontMetrics = getFontMetrics(BG_STRING_FONT);
      int w = fontMetrics.stringWidth(BACKGROUND_STRING);
      int h = fontMetrics.getHeight();

      bgStringX = (PREF_W - w) / 2;
      bgStringY = (PREF_H - h) / 2;
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g.setFont(BG_STRING_FONT);
      g.setColor(Color.LIGHT_GRAY);
      g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
            RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
      g.drawString(BACKGROUND_STRING, bgStringX, bgStringY);

      if (image != null) {
         g.drawImage(image, imgX, imgY, this);
      }
   }

   private class TimerListener implements ActionListener {
      public void actionPerformed(java.awt.event.ActionEvent e) {
         for (Direction dir : Direction.values()) {
            if (dirMap.get(dir)) {
               imgX += dir.getX() * TRANSLATE_SCALE;
               imgY += dir.getY() * TRANSLATE_SCALE;
            }
         }
         repaint();
      };
   }

   enum Direction {
      Up(KeyEvent.VK_UP, 0, -1), Down(KeyEvent.VK_DOWN, 0, 1), Left(
            KeyEvent.VK_LEFT, -1, 0), Right(KeyEvent.VK_RIGHT, 1, 0);

      private int keyCode;
      private int x;
      private int y;

      private Direction(int keyCode, int x, int y) {
         this.keyCode = keyCode;
         this.x = x;
         this.y = y;
      }

      public int getKeyCode() {
         return keyCode;
      }

      public int getX() {
         return x;
      }

      public int getY() {
         return y;
      }

   }

   private static void createAndShowGui() {
      AnimateExample mainPanel = new AnimateExample();

      JFrame frame = new JFrame("Animate Example");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

它将创建这个GUI:

 类似资料:
  • 我正在用Java编写一个游戏,我开始使用drawRect()方法来表示玩家、敌人和射击。一切都很好。然后我决定试着装腔作势。我发现自己在创造。每个对象的png图像,并使用Graphics2D drawImage()方法。一切开始放缓。有没有其他方法可以加快这一进程? 我的动画基于摆动计时器 有关于动画的提示或教程吗?谢谢

  • 我一直在使用Swing编写一个简单的动画,其中有一个JFrame,只要JFrame收到鼠标点击,就会开始一个涟漪动画。我使用一个内部动画类,该类为每个动画扩展JPanel,以防同时播放多个动画(我不知道这是否是最好的方式)。当我单击时,我向JFrame添加一个新动画,并将单击的坐标传递给动画。但是,动画重绘/绘制组件方法不起作用。在我的理解中,repaint应该调用paint/paintCompo

  • 问题内容: 我从来没有能够使Java 6启动屏幕正常工作。 我已经尝试了所有我能想到的。我的manifest.mf包含: 我将文件“ 放在源代码树的根目录中,并验证它是否已放入生成的.jar文件的根目录中。我还在不同的地方尝试过,再次确认其在jar中的位置,并将路径放入SplashScreen-Image中。 它永远不会出现。 尝试在运行时获取启动屏幕失败: 飞溅对我而言始终为空。 关于我在这里缺

  • 问题内容: 我想在应用程序中显示GIF动画图像。我发现,Android本身并不支持动画GIF的困难方式。 但是,它可以使用AnimationDrawable显示动画: 开发>指南>图像和图形> Drawables概述 该示例使用在应用程序资源中另存为帧的动画,但是我需要直接显示动画gif。 我的计划是将动画GIF分解为帧,并将每个帧作为可绘制对象添加到AnimationDrawable中。 有谁知

  • 所以我在谷歌上搜索了这个,但我能在上面找到任何东西:我在代码中调用了这个方法 然后,我添加了一个JProgressBar,称为进度条,并在单击GUI上的按钮时调用此代码: Progresslabel只是一个显示进度的标签。现在,当我这样做时,进度条显示如下: http://i.imgur.com/gXp5ByH.png 与其他应用程序上的情况不同: http://i.imgur.com/M61Cd

  • 动画剪辑 动画剪辑是 Unity 动画系统的核心元素。Unity 不仅支持从外部源导入动画,而且支持在编辑器的动画视图中创建和编辑动画(剪辑)。 从外部源导入动画 从外部源导入的动画剪辑可能包括: 动作捕捉工作室捕捉的人形动画 设计师通过外部 3D 程序(例如 3D Max 或 Maya)创建的动画 第三方的动画集合库(例如来自 Unity Asset store) 导入的单个时间线等分切割为多个