[英]How to display an images instantly in Java Applet?
我在Java Applet中創建了一個簡單的內存游戲。 卡有問題。 在第一次出現時,圖像需要一些額外的加載時間。 如何解決? 我需要在卡片翻轉后立即顯示圖像。
我顯示加載屏幕,直到應用程序不在AppStates.READY
或AppStates.WAIT_FOR_START
狀態,但它沒有幫助。
Memo.cs - 帶圖像加載的主類
public class Memo extends JApplet {
//...
public void init() {
//...
try {
SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { createGUI(); }});
}
catch(Exception e) {
e.printStackTrace();
}
}
private void createGUI() {
final Model model = new Model(...);
final View view = new View(model);
getContentPane().add(view, BorderLayout.CENTER);
setBackground(backgroundColor);
setPreferredSize(new Dimension(width, height));
model.setLoading(loadImages(loadingPath, format, 1));
model.setCardsImages(loadImages(cardImagePath, format, 13));
//...
model.setAppState(AppStates.PROCESS);
model.startNewGame();
view.repaint();
}
private Image[] loadImages(String path1, String path2, int count) {
Image[] imgs = new Image[count];
for(int i = 0; i < count; ++i) {
imgs[i] = getImage(getCodeBase(), path1 + i + path2);
}
return imgs;
}
}
Model.cs - 保存圖像和應用程序狀態,init板
public class Model {
//...
private AppStates appState;
private Image[] cardsImages;
public Model(...) {
//...
appState = AppStates.INIT;
}
public void startNewGame() {
setAppState(AppStates.PROCESS);
//... - init board - table with images' id
setAppState(AppStates.WAIT_FOR_START);
}
public void setCardsImages(Image[] cardsImages) {
this.cardsImages = cardsImages;
}
public Image getCardsImage(int v) {
return cardsImages[v];
}
public AppStates getAppState() {
return appState;
}
public void setAppState(AppStates appState) {
this.appState = appState;
//...
}
//...
}
View.cs - 顯示板
public class View extends JPanel {
//...
private Model model;
public View(Model model) {
this.model = model;
//...
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
if(model != null) {
switch (model.getAppState()) {
//...
case WAIT_FOR_START:
case READY:
//...
drawBoard(g2d, model.getBoard(), model.getStates(), model.getFrontTypes());
break;
}
}
repaint();
}
private void drawBoard(Graphics2D g2d, int[][] board, int[][] states, int[][] frontTypes) {
if(board != null && states != null && board.length > 0 && states.length > 0) {
for(int x = 0; x < board.length; x++) {
for(int y = 0; y < board[x].length; y++) {
if(states[x][y] != Model.HIDE) {
Image img = null;
//...
img = model.getCardsImage(board[x][y]);
g2d.drawImage(
img,
model.getFirstCardX() + x * model.getCardDistance() + x * model.getCardWidth(),
model.getFirstCardY() + y * model.getCardDistance() + y * model.getCardHeight(),
model.getCardWidth(),
model.getCardHeight(),
null);
//...
}
}
}
}
}
}
來自JavaDocs ..
public Image getImage(URL url)
..
無論圖像是否存在,此方法始終立即返回。 當此applet嘗試在屏幕上繪制圖像時,將加載數據。
請改用ImageIO.read(URL)
。 此方法將“阻止”(它將停在該代碼行),直到讀取圖像。 所以當應用程序。 去使用圖像,它已經完全加載。
解決問題的另一種方法(不是你想要的方式)是改變..
g2d.drawImage(
img,
model.getFirstCardX() + x * model.getCardDistance() + x * model.getCardWidth(),
model.getFirstCardY() + y * model.getCardDistance() + y * model.getCardHeight(),
model.getCardWidth(),
model.getCardHeight(),
null);
至..
g2d.drawImage(
img,
model.getFirstCardX() + x * model.getCardDistance() + x * model.getCardWidth(),
model.getFirstCardY() + y * model.getCardDistance() + y * model.getCardHeight(),
model.getCardWidth(),
model.getCardHeight(),
this);
如果圖像是異步加載的(例如,使用Applet.getImage(URL)
),GUI會在更多可用時通知重繪。
你可以利用Swing
的雙緩沖,並在一切准備就緒時立即顯示。
如果您需要在中間進行,可以保留預先制作的副本並在需要時顯示。
預取圖像的一種方法是使用MediaTracker
。 使用此類可確保在給定點加載圖像。 以下是文檔中的優秀演示:
import java.applet.Applet;
import java.awt.Color;
import java.awt.Image;
import java.awt.Graphics;
import java.awt.MediaTracker;
public class ImageBlaster extends Applet implements Runnable {
MediaTracker tracker;
Image bg;
Image anim[] = new Image[5];
int index;
Thread animator;
// Get the images for the background (id == 0)
// and the animation frames (id == 1)
// and add them to the MediaTracker
public void init() {
tracker = new MediaTracker(this);
bg = getImage(getDocumentBase(),
"images/background.gif");
tracker.addImage(bg, 0);
for (int i = 0; i < 5; i++) {
anim[i] = getImage(getDocumentBase(),
"images/anim"+i+".gif");
tracker.addImage(anim[i], 1);
}
}
// Start the animation thread.
public void start() {
animator = new Thread(this);
animator.start();
}
// Stop the animation thread.
public void stop() {
animator = null;
}
// Run the animation thread.
// First wait for the background image to fully load
// and paint. Then wait for all of the animation
// frames to finish loading. Finally, loop and
// increment the animation frame index.
public void run() {
try {
tracker.waitForID(0);
tracker.waitForID(1);
} catch (InterruptedException e) {
return;
}
Thread me = Thread.currentThread();
while (animator == me) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break;
}
synchronized (this) {
index++;
if (index >= anim.length) {
index = 0;
}
}
repaint();
}
}
// The background image fills the frame so we
// don't need to clear the applet on repaints.
// Just call the paint method.
public void update(Graphics g) {
paint(g);
}
// Paint a large red rectangle if there are any errors
// loading the images. Otherwise always paint the
// background so that it appears incrementally as it
// is loading. Finally, only paint the current animation
// frame if all of the frames (id == 1) are done loading,
// so that we don't get partial animations.
public void paint(Graphics g) {
if ((tracker.statusAll(false) & MediaTracker.ERRORED) != 0) {
g.setColor(Color.red);
g.fillRect(0, 0, size().width, size().height);
return;
}
g.drawImage(bg, 0, 0, this);
if (tracker.statusID(1, false) == MediaTracker.COMPLETE) {
g.drawImage(anim[index], 10, 10, this);
}
}
}
如果您可以保證這將始終在Java 1.4或更高版本上運行,則可以使用[ImageIO.read][2]
來獲取圖像。 它會等到圖像加載完畢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.