兩件事情......
首先,調用事件分派線程中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;
}
}
}
使用邏輯和一致的代碼格式風格!代碼縮進旨在幫助人們遵循程序流程。 –