Java Animate JLabel

因此,我正在创建一个基本应用程序,我希望在屏幕底部具有一个JLabel,该JLabel从左下角开始,然后在设置的时间内将动画样式移动到右下角,并在中心放置一个静态图像。为此,我使用BorderLayout用JPanel创建了一个JFrame。有一个JLabel,其中ImageIcon已添加到BorderLayout.CENTER,而JPanel位于BorderLayout.SOUTH。我的代码虽然草率编写,而且远非美观,但它是:

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,但是现在我什至无法将图像显示在屏幕上。

我也了解到,我很可能将无法使用FlowLayout,因为我了解它不允许您设置组件的位置。我尝试使用null布局,但是使用null布局时,不会显示带有边框的空JLabel。我几乎无法辨认出边框底部的边框顶部,但是即使使用setLocation,我也无法将其显示在想要的位置。

显然,我的思考过程存在缺陷,因此可以提供任何帮助。

回答:

15

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

另外,你的意思是:

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

请阐明你要达到的效果。

另外,

我也了解到,我很可能将无法使用FlowLayout,因为我了解它不允许你设置组件的位置。我尝试使用null布局,但是使用null布局时,不会显示带有边框的空JLabel。我几乎无法辨认出边框底部的边框顶部,但是即使使用setLocation,我也无法将其显示在想要的位置。

不,在这种情况下请不要使用空布局。有更好的布局管理器,可以帮助你以更清洁,更独立于平台的方式构建应用程序。

编辑3

关于:

为了明确起见,在屏幕底部,我需要在最右上角有一个JLabel,然后在摆动计时器中,JLabel将逐渐向左移动,直到离开屏幕为止。如果我可以使setLocation正常工作,则基本前提是将变量x设置为600,然后每秒将x递减50,然后在屏幕上的新位置重新绘制JLabel。基本动画。

我将在屏幕底部创建一个JPanel,以保留你的JLabel或通过覆盖JLabel的paintComponent(…)方法来显示没有JLabel的图像。如果将其用作容器,则可以,其布局应为null,但GUI的其余部分不应使用null布局。Swing计时器只需更改JLabel的位置,然后调用repaint()其JPanel /容器。如果走后一条路线,则可以paintComponent(…)使用JPanel的方法绘制图像,g.drawImage(myImage, x, y)计时器将更改x和/或y并调用repaint()绘制的JPanel。

另外,你可能不想在计时器中继续添加JLabel,而只是移动已经在GUI中显示的JLabel。

另外,为避免出现焦点问题,请不要使用KeyListener来捕获击键输入,而应使用键绑定。Google会指导你找到有关此结构的出色教程。

编辑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();

}

});

}

}

以上是 Java Animate JLabel 的全部内容, 来源链接: utcz.com/qa/398032.html

回到顶部