两件事情......
首先,调用事件分派线程中Thread.sleep(2000);
将阻止EDT从事件队列中处理事件,包括油漆事件。
其次,Frame
没有paintComponent
。
添加@Override
注释并尝试调用super.paintComponent
会突出显示此问题,因为代码不会编译。
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
首先,首先使用JPanel
来保存您的核心逻辑并执行自定义绘画。
其次,使用javax.swing.Timer
进行动画。有关详细信息,
更新
的基本概念是相对简单的见How to use Swing Timers。你需要某种第二/后台线程,它可以产生输出变化之间的延迟。然后,您需要根据您尝试显示的信息类型在每次延迟之前更新UI。
实现变得棘手,因为秋千,最喜欢的GUI框架,是单线程的,而不是线程安全的。
这意味着,您不能阻止GUI线程,这样做会阻止UI被重新绘制等等,并且您必须在GUI线程的上下文内更新任何UI组件的状态。
这意味着虽然您可以使用Thread
在后台运行,但您必须确保只对EDT中的所有UI进行更改/修改。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;
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 MorseCodeTest {
public static void main(String[] args) {
new MorseCodeTest();
}
public MorseCodeTest() {
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 static final int GAP = 500;
public static final int DOT = 1000;
public static final int DASH = 4000;
public interface Transmitter {
public void setTap(boolean tap);
}
public class TestPane extends JPanel implements Transmitter {
private MorseCode code;
private boolean tapped;
public TestPane() {
code = MorseCode.create('A').addDot().addDash();
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
Signalar signalar = new Signalar(TestPane.this, code);
signalar.execute();
}
});
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (tapped) {
Graphics2D g2d = (Graphics2D) g.create();
int diameter = Math.min(getWidth(), getHeight())/2;
int x = (getWidth() - diameter)/2;
int y = (getHeight() - diameter)/2;
g2d.fillOval(x, y, diameter, diameter);
g2d.dispose();
}
}
@Override
public void setTap(boolean tap) {
tapped = tap;
repaint();
}
}
public class Signalar extends SwingWorker<Void, Boolean> {
private final MorseCode code;
private final Transmitter transmitter;
public Signalar(Transmitter transmitter, MorseCode code) {
this.code = code;
this.transmitter = transmitter;
}
@Override
protected void process(List<Boolean> chunks) {
transmitter.setTap(chunks.get(chunks.size() - 1));
}
@Override
protected Void doInBackground() throws Exception {
for (Tone tone : code.getTones()) {
publish(true);
Thread.sleep(tone.getDelay());
publish(false);
Thread.sleep(GAP);
}
return null;
}
}
public static class Tone {
private final int delay;
public Tone(int delay) {
this.delay = delay;
}
public int getDelay() {
return delay;
}
}
public static class DashTone extends Tone {
public DashTone() {
super(DASH);
}
}
public static class DotTone extends Tone {
public DotTone() {
super(DOT);
}
}
public static class MorseCode {
private final char value;
private final List<Tone> tones;
public static MorseCode create(char value) {
MorseCode code = new MorseCode(value);
return code;
}
public MorseCode(char value) {
this.value = value;
this.tones = new ArrayList<>(25);
}
public char getValue() {
return value;
}
public MorseCode addDash() {
return addTone(new DashTone());
}
public MorseCode addDot() {
return addTone(new DotTone());
}
public MorseCode addTone(Tone tone) {
tones.add(tone);
return this;
}
public Iterable<Tone> getTones() {
return tones;
}
}
}
使用逻辑和一致的代码格式风格!代码缩进旨在帮助人们遵循程序流程。 –