Die Verwendung von Threading ist bei Swing-Anwendungen falsch. Sie sollten nicht versuchen, Komponenten in einem Hintergrund-Thread hinzuzufügen oder zu entfernen, sondern stattdessen einen Swing-Timer für den Swing-Ereignis-Thread verwenden.
Auch, was meinen Sie:
ich Sie versuchen zu erreichen, ein Scrollen JLabel am unteren Rand des Bildschirms
Bitte klären Sie die Wirkung haben soll.
Auch in Bezug auf,
Ich verstehe auch, dass ich höchstwahrscheinlich nicht in der Lage sein, dies zu verwenden Flowlayout für, wie ich es verstehe nicht zulässt, dass Sie die Position Ihrer Komponenten einzustellen. Ich habe versucht, Null-Layout zu verwenden, aber mit Null-Layout wird das leere JLabel mit einem Rahmen nicht angezeigt. Ich kann den oberen Rand des Randes am unteren Rand des Rahmens kaum ausmachen, aber selbst mit setLocation kann ich nicht erreichen, dass er dort erscheint, wo ich es möchte.
Nein, verwenden Sie für diese Situation kein Null-Layout. Es gibt viel bessere Layout-Manager, die Ihnen helfen können, Ihre Anwendung auf eine plattformunabhängigere Weise zu erstellen.
bearbeiten 3
In Bezug auf:
Um zu klären, am unteren Rand des Bildschirms möchte ich ein JLabel auf der rechten Ecke, dann in den Swing-Timer wird die JLabel allmählich auf die bewegen verlassen, bis es den Bildschirm verlässt. Wenn ich setLocation zum Arbeiten bringen könnte, wäre die Grundvoraussetzung, eine Variable x auf 600 und dann jede zweite Dekrementierung x auf etwa 50 zu setzen und dann JLabel an der neuen Position auf dem Bildschirm neu zu zeichnen. Grundlegende Animation
würde ich ein JPanel für den unteren Rand des Bildschirms für die Zwecke erstellen entweder Ihre JLabel halten oder ohne JLabel Anzeige des Bildes durch Überschreiben seine paintComponent(...)
Methode. Wenn Sie es als Container verwenden, dann sollte sein Layout ja null sein, aber der Rest der GUI sollte kein Null-Layout verwenden. Der Swing-Timer würde einfach die Position von JLabel ändern und dann repaint()
auf seinem JPanel/Container aufrufen. Wenn Sie die letztere Route gehen, würden Sie das Bild in der paintComponent(...)
Methode von JPanel zeichnen, die g.drawImage(myImage, x, y)
verwendet, und Ihr Timer würde X und/oder Y ändern und repaint()
auf der Zeichnung JPanel aufrufen.
Außerdem möchten Sie wahrscheinlich kein JLabel in Ihrem Timer hinzufügen, sondern einfach das JLabel, das bereits in der GUI angezeigt wird, verschieben.
Um Fokusprobleme zu vermeiden, verwenden Sie keinen KeyListener, um die Tasteneingabe zu erfassen, sondern Key Bindings. Google leitet Sie zu einem großartigen Tutorial zu diesem Konstrukt.
bearbeiten 4
Zum Beispiel:
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();
}
});
}
}
Welche dieser GUI schaffen:
+1. Das Festlegen des Standorts bei Verwendung eines LayoutManagers hat keine Auswirkungen. Es ist der LayoutManager, der den Ort bestimmt – Robin
Ich hatte tatsächlich den Timer vor, aber jemand sagte mir, es wäre besser, ScheduledExecutorService zu verwenden.Es ist kein Problem, es wieder mit dem Swing-Timer zu verwenden. Ich bearbeite die Frage – awestover89
Wenn immer noch nicht funktioniert, dann erstellen Sie ein einfaches kompilierbares und lauffähiges Programm, das Ihr Problem demonstriert und Online-Bilder für alle verwendet, ein [sscce] (http://sscce.org). –