因此,我正在创建一个基本应用程序,我希望在屏幕底部具有一个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(); } }); } }