在Swing应用程序中,您使用线程的方式是错误的。您不应该尝试在后台线程中添加或删除组件,而应该使用Swing计时器在Swing事件线程上执行此操作。
另外,您说的:
我想在屏幕底部有一个滚动的JLabel
请澄清您试图实现的效果。
还有关于:
我也知道我很可能无法在这种情况下使用FlowLayout,因为我了解它不允许您设置组件的位置。 我试图使用空布局,但是使用空布局时,带边框的空JLabel不会出现。我几乎看不到边框顶部在框架底部边缘,但即使使用setLocation,我也无法将其显示在想要的位置。
不要为此情况使用null布局。 有更好的布局管理器可以帮助您以更清洁和更独立于平台的方式构建应用程序。
第3次编辑
关于:
澄清一下,在屏幕底部,我想在右下角放置一个JLabel,然后在摆动计时器中,JLabel将逐渐向左移动,直到离开屏幕。如果我可以让setLocation起作用,基本前提将是将变量x设置为600,然后每秒将x减少50,然后在屏幕的新位置上重新绘制JLabel。基本动画。
我会为屏幕底部创建一个JPanel,以便用于容纳您的JLabel或通过覆盖其paintComponent(...)
方法显示图像而无需JLabel。 如果将其用作容器,则其布局应为空,但是GUI的其余部分不应使用null布局。 Swing计时器将简单地更改JLabel的位置,然后在其JPanel / 容器上调用repaint()
。 如果选择后者,您将使用g.drawImage(myImage,x,y)
在JPanel的paintComponent(...)
方法中绘制图像,并且您的计时器将更改x和/或y并在绘图JPanel上调用repaint()
。
此外,您可能不想在计时器中不断添加JLabel,而仅仅是移动已经显示在GUI中的JLabel。
另外,为避免焦点问题,请勿使用KeyListener捕获按键输入,而是使用键绑定。 谷歌将为您指导这个结构的出色教程。
第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();
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition);
ActionMap actionMap = getActionMap();
for (final Direction dir : Direction.values()) {
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);
}
});
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界面: