La réponse se résume à ce que vous voulez réaliser ...
Les choses à l'importation à retenir sont, Swing est simple environnement fileté, qui est, il est prévu que toutes les interactions, les changements, les modifications, Les mises à jour et les créations de l'interface utilisateur sont effectuées dans le contexte du fil d'envoi des événements.
Toute action qui bloque l'EDT (telle que sleep
, wait
, etc.) empêchera l'EDT de repeindre l'interface utilisateur ou de répondre à de nouveaux événements.
Une façon d'y parvenir est par l'utilisation de javax.swing.Timer
Ceci est par exemple très simple en utilisant 3 minuteries enchaînées ensemble. Personnellement, j'utiliser une minuterie unique configurée pour une courte durée cocher et vérifier si le délai requis est survenu et puis changer l'état en conséquence, mais cela devient le point à travers ...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SimpleTimer {
public static void main(String[] args) {
new SimpleTimer();
}
public SimpleTimer() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Timer red;
private Timer green;
private Timer yellow;
private Color color = Color.GREEN;
private Point spot;
public TestPane() {
red = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
color = Color.RED;
green.start();
repaint();
}
});
green = new Timer(2000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
color = Color.GREEN;
yellow.start();
repaint();
}
});
yellow = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
color = Color.YELLOW;
red.start();
repaint();
}
});
red.setRepeats(false);
green.setRepeats(false);
yellow.setRepeats(false);
green.start();
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
spot = e.getPoint();
repaint();
}
});
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int radius = 20;
int x = (getWidth() - radius)/2;
int y = (getHeight() - radius)/2;
g2d.setColor(color);
g2d.fillOval(x, y, radius, radius);
if (spot != null) {
x = spot.x - 5;
y = spot.y - 5;
g2d.setColor(Color.RED);
g2d.drawOval(x, y, 10, 10);
g2d.setColor(Color.YELLOW);
g2d.fillOval(x, y, 10, 10);
}
g2d.dispose();
}
}
}
Une autre option serait d'utiliser un SwingWorker
, cela permet de faire une sorte de traitement dans un thread d'arrière-plan (en laissant l'EDT en cours d'exécution), mais fournit des méthodes par lesquelles vous pouvez simplement synchroniser les résultats avec l'EDT.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SimpleTimer {
public static void main(String[] args) {
new SimpleTimer();
}
public SimpleTimer() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Color color = Color.GREEN;
private Point spot;
public TestPane() {
new Switcher().execute();
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
spot = e.getPoint();
repaint();
}
});
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int radius = 20;
int x = (getWidth() - radius)/2;
int y = (getHeight() - radius)/2;
g2d.setColor(color);
g2d.fillOval(x, y, radius, radius);
if (spot != null) {
x = spot.x - 5;
y = spot.y - 5;
g2d.setColor(Color.RED);
g2d.drawOval(x, y, 10, 10);
g2d.setColor(Color.YELLOW);
g2d.fillOval(x, y, 10, 10);
}
g2d.dispose();
}
public class Switcher extends SwingWorker<Void, Color> {
@Override
protected void process(List<Color> chunks) {
color = chunks.get(chunks.size() - 1);
repaint();
}
@Override
protected Void doInBackground() throws Exception {
while (true) {
publish(Color.GREEN);
Thread.sleep(2000);
publish(Color.YELLOW);
Thread.sleep(500);
publish(Color.RED);
Thread.sleep(2000);
}
}
}
}
}
Découvrez Concurrency in Swing pour plus de détails
C'est ... pas ce que font les minuteries. –
D'accord, merci. Si vous savez comment, alors pouvez-vous répondre comment ai-je 3 tâches séquentielles se produisent dans une boucle avec le temps entre eux l'un après l'autre? – Yesha
Vous ne voulez pas que le programme attende. L'idée est que chaque fois qu'une minuterie tic-tac va changer l'état du programme est d'une certaine façon, qui est ensuite peint et la minuterie suivante commence ... – MadProgrammer