讓我們開始無線小應用程序正式是一種死硬的技術,我不會浪費時間讓它們工作,相反,我會把你的努力集中在API的其他領域。有關更多詳細信息,請參閱Java Plugin support deprecated和Moving to a Plugin-Free Web。
您不應該在事件分派線程的上下文內(或者執行任何其他長時間運行或阻塞操作)並且尤其不能從paint方法的上下文中調用Thread.sleep
。有關更多詳細信息,請參閱Concurrency in Java。
您不應該調用任何可能直接或間接生成重繪的方法,繪畫僅用於繪畫而不用其他任何東西,否則可能會導致EDT不穩定並導致程序無響應。
在Swing中製作動畫的一個簡單解決方案是使用Swing Timer
,它不會阻止EDT,但會在EDT的內容中觸發它的更新,從而更安全地從內部更新UI。
有關更多詳細信息,請參見How to use Swing Timers。
我也建議你看看Painting in AWT and Swing和Performing Custom Painting因爲如果你打算做任何類型的自定義繪畫,你應該有一些瞭解如何繪畫過程的作品。
KeyListener
是一個低級別的API,它從鍵盤焦點問題受到影響(如果它註冊到組件沒有鍵盤焦點,也不會產生事件),相反,你應該使用Key Bindings API來代替。
在下面的例子中,有兩件事發生。該是Timer
這是更新「運行時間」值,當你按下ñ關鍵,它更新一個turn
變量
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class GameGraphic {
public static void main(String[] args) {
new GameGraphic();
}
public GameGraphic() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new GamePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GamePane extends JPanel {
private int turn = 0;
private long runtime;
public GamePane() {
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_N, 0), "next");
actionMap.put("next", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("...");
turn++;
repaint();
}
});
long startTime = System.currentTimeMillis();
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
runtime = System.currentTimeMillis() - startTime;
repaint();
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth();
int height = getHeight();
FontMetrics fm = g2d.getFontMetrics();
String text = Integer.toString(turn);
int x = (width - fm.stringWidth(text))/2;
int y = ((height - fm.getHeight())/2) + fm.getAscent();
g2d.drawString(text, x, y);
text = Long.toString(runtime);
x = width - fm.stringWidth(text);
y = height - fm.getHeight() + fm.getAscent();
g2d.drawString(text, x, y);
g2d.dispose();
}
}
}
[棄用Java插件的支持(http://www.gizmodo.com .au/2016/01/rest-in-hell-java-plug-in /)和[移至無插件網頁](https://blogs.oracle。com/java-platform-group/entry/moving_to_a_plugin_free) – MadProgrammer
因爲我知道有些人會提出這個建議,所以通常不會推薦'KeyListener',你應該看看[Key Bindings API](http://docs.oracle.com /javase/tutorial/uiswing/misc/keybinding.html),它旨在解決許多與'KeyListener'相關的問題API – MadProgrammer
不要在'paint'方法中調用'Thread.sleep',這不是應該完成動畫,看看[併發中的Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/)和[如何使用Swing定時器](http://docs.oracle.com .com/javase/tutorial/uiswing/misc/timer.html)以獲取更多詳細信息 – MadProgrammer