Java的动画的JLabel [英] Java Animate JLabel

查看:294
本文介绍了Java的动画的JLabel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我创造,我想有那个开始在左下角和动作,动画风格,到了右侧底角在设定的时间在屏幕底部的JLabel的基本应用程序,以及静态图像在中心。要做到这一点,我创建了使用BorderLayout的一个JPanel的JFrame。这里是一个ImageIcon一个JLabel添加到BorderLayout.CENTER和一个JPanel在BorderLayout.SOUTH。我的code,而匆匆写和pretty远,方法是:

So I am creating a basic application that I want to have a JLabel at the bottom of the screen that starts at the left bottom corner and moves, animation style, to the right bottom corner in a set time, and a static image in the center. To do this, I created a JFrame with a JPanel using BorderLayout. There is a JLabel with an ImageIcon added to BorderLayout.CENTER and a JPanel at BorderLayout.SOUTH. My code, while hastily written and far from pretty, is:

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();
}

}

在该中心的JLabel的ImageIcon的出现罚款,并带有边框空的JLabel出现在底部,但我不能用箭头图像第二个JLabel来显示在屏幕上。最后,我会变成scheduleAtFixedRate连续移动的JLabel,但现在我甚至不能出现在屏幕上的图像。

The ImageIcon in the center JLabel appears fine, and the empty JLabel with a border appears at the bottom, but I cannot get the second JLabel with the arrow image to show up on screen. Eventually I will change to scheduleAtFixedRate to continuously move the JLabel, but right now I can't even get the image to appear on screen.

我也明白,我将最有可能无法使用的FlowLayout这一点,据我了解它不允许你设置你的组件的位置。我试着用空布局,但用null布局边界空的JLabel不会出现。我可以勉强出了边界的顶部在框架的底部边缘,但即使我的setLocation不能让它显得它,我想。

I also understand that I will most likely not be able to use FlowLayout for this, as I understand it does not allow you to set the location of your components. I tried using null layout, but with null layout the empty JLabel with a border does not appear. I can barely make out the top of the border at the bottom edge of the frame, but even with setLocation I cannot get it to appear where I want it to.

显然,我的思维过程是有缺陷的,所以任何帮助将是AP preciated。

Obviously, my thought process is flawed, so any help would be appreciated.

推荐答案

您使用线程都是错误的Swing应用程序。你不应该试图在后台线程中添加或删除组件,而是应该使用一个Swing计时器做到这一点Swing事件线程上。

Your use of threading is all wrong for Swing applications. You should not be trying to add or remove components in a background thread but instead should use a Swing Timer to do this on the Swing event thread.

另外,你是什么意思是:

Also, what do you mean by:

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

I want to have a scrolling JLabel at the bottom of the screen

请澄清你想达到的效果。

Please clarify the effect you're trying to achieve.

另外关于

我也明白,我将最有可能无法使用的FlowLayout这一点,据我了解它不允许你设置你的组件的位置。我试着用空布局,但用null布局边界空的JLabel不会出现。我可以勉强出了边界的顶部在框架的底部边缘,但即使我的setLocation不能让它显得它,我想。

I also understand that I will most likely not be able to use FlowLayout for this, as I understand it does not allow you to set the location of your components. I tried using null layout, but with null layout the empty JLabel with a border does not appear. I can barely make out the top of the border at the bottom edge of the frame, but even with setLocation I cannot get it to appear where I want it to.

没有,没有为这种情况下使用空布局。有很多更好的布局管理器,可以帮助你在一个更清洁更独立于平台的方式来构建应用程序。

No, don't use null layout for this situation. There are much better layout managers that can help you build your application in a cleaner more platform-independent manner.

修改3 结果
关于:

Edit 3
Regarding:

要澄清,在屏幕的底部我想一个JLabel最右侧的角落,然后在挥杆计时器,选择JLabel将逐步直到将屏幕向左移动。如果我能得到的setLocation工作,基本的premise将有一个变量x设置为600,再由每秒减小量X说50,然后在屏幕上的新位置重画的JLabel。基本的动画。

To clarify, at the bottom of the screen I want a JLabel at the far right corner, then in the swing timer, the JLabel will gradually move to the left until it leaves the screen. If I could get setLocation to work, the basic premise would be to have a variable x set to 600, and then every second decrement x by say 50 and then redraw the JLabel at the new location on the screen. Basic animation.

我将创建一个JPanel在屏幕的底部或者牵着你的JLabel或通过重写没有一个JLabel显示图像的的paintComponent(...)方法。如果你使用它作为一个容器,那么,它的布局应该是空的,但GUI的其余部分不应该使用空布局。 Swing的计时器将简单地改变JLabel的位置,然后调用重绘()它的JPanel /容器上。如果你去了后一条道路,你会绘制图像在JPanel的的paintComponent(...)使用 g.drawImage(MYIMAGE,X的方法, Y),和你的计时器会改变x和/或y并调用重绘()在图纸上的JPanel。

I would create a JPanel for the bottom of the screen for the purposes of either holding your JLabel or displaying the image without a JLabel by overriding its paintComponent(...) method. If you use it as a container, then yes, its layout should be null, but the rest of the GUI should not be using null layout. The Swing Timer would simply change the JLabel's location and then call repaint() on its JPanel/container. If you go the latter route, you would draw the image in the JPanel's paintComponent(...) method using g.drawImage(myImage, x, y), and your timer would change x and/or y and call repaint() on the drawing JPanel.

此外,您可能不希望在你的定时器添加一个JLabel而是简单地移动这已经显示在GUI中的JLabel。

Also, you likely do not want to keep adding a JLabel in your timer but rather simply moving the JLabel that's already displayed in the GUI.

另外,为了避免焦点问题,不使用的KeyListener捕捉键盘输入,而是使用键绑定。谷歌将引导您对这个结构有很大的教程。

Also, to avoid focus issues, don't use a KeyListener to capture keystroke input but rather use Key Bindings. Google will direct you to a great tutorial on this construct.

修改4 结果
例如:

Edit 4
For example:

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:

Which will create this GUI:

这篇关于Java的动画的JLabel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆