java你能帮我指导这个Swing应用程序正确加载图像吗?
我是Java新手,已经构建了一个简单的Swing应用程序,它以全屏模式运行,定期轮询数据源,并根据所述数据源显示不同的输出。我创建了一个简短的MCVE来展示我在做什么
简言之,我的问题是:我有一个应该始终显示的背景图像,和一个只应该在特定情况下显示的前景图像。不幸的是,第一次加载它们似乎需要几秒钟的时间,这意味着在加载它们并重新绘制屏幕之前,屏幕是白色的。为了解决这个问题,我跟踪一个私有成员的“周期”数,在开始时的特定值下,我强制它尝试绘制这些图像。然而,这感觉非常“黑客”,我更愿意学习在Swing应用程序中加载和显示图像的正确方法
Main。java
import javax.swing.*;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
try {
final MyDisplay myDisplay = new MyDisplay();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
MyDisplay。java
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.net.URL;
public class MyDisplay extends Thread {
private long cycleCounter = 0;
private MyDataSource dataSource;
private MyFrame myFrame;
public MyDisplay() throws IOException {
dataSource = new MyDataSource();
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = env.getDefaultScreenDevice();
myFrame = new MyFrame(device);
final int windowWidth = myFrame.getWindowWidth();
final int windowHeight = myFrame.getWindowHeight();
final URL bgPath = this.getClass().getResource("/bg.png");
final ImageIcon bgLoader = new ImageIcon(bgPath);
final Image bgImage = bgLoader.getImage().getScaledInstance(windowWidth, windowHeight, Image.SCALE_SMOOTH);
myFrame.setBgImage(bgImage);
final URL fgPath = this.getClass().getResource("/fg.png");
final ImageIcon fgLoader = new ImageIcon(fgPath);
final Image fgImage = fgLoader.getImage().getScaledInstance(200, 85, Image.SCALE_SMOOTH);
myFrame.setFgImage(fgImage);
start();
}
@Override
public void run() {
try {
while (true) {
if (dataSource.hasData()) {
myFrame.showData();
} else {
myFrame.clearData();
}
// THIS IS THE "HACKY" PART
cycleCounter++;
if (cycleCounter == 20) {
myFrame.showData();
} else if (cycleCounter == 21) {
myFrame.clearData();
}
// END OF HACK
Thread.sleep(100);
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
MyFrame。java
import javax.swing.*;
import java.awt.*;
public class MyFrame extends JFrame {
private GraphicsDevice device;
private MyPanel myPanel;
public MyFrame(GraphicsDevice device) {
super(device.getDefaultConfiguration());
this.device = device;
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception ignored) { }
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setUndecorated(true);
setResizable(false);
setVisible(true);
myPanel = new MyPanel();
add(myPanel);
pack();
device.setFullScreenWindow(this);
}
public void setBgImage(Image bgImage) {
myPanel.setBgImage(bgImage);
}
public void setFgImage(Image fgImage) {
myPanel.setFgImage(fgImage);
}
public int getWindowHeight() {
final Double height = device.getDefaultConfiguration().getBounds().getHeight();
return height.intValue();
}
public int getWindowWidth() {
final Double width = device.getDefaultConfiguration().getBounds().getWidth();
return width.intValue();
}
public void showData() {
myPanel.showData();
}
public void clearData() {
myPanel.clearData();
}
}
MyPanel。java
import javax.swing.*;
import java.awt.*;
public class MyPanel extends JPanel {
private boolean showData = false;
private Image bgImage;
private Image fgImage;
public MyPanel() {
setFocusable(true);
requestFocusInWindow();
}
public void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
setBackground(Color.WHITE);
if (bgImage != null) {
graphics.drawImage(bgImage, 0, 0, null, null);
}
if (showData) {
if (fgImage != null) {
graphics.drawImage(fgImage, 0, 0, 200, 85, null, null);
}
}
}
public void showData() {
if (showData == false) {
showData = true;
repaint();
}
}
public void clearData() {
if (showData == true) {
showData = false;
repaint();
}
}
public void setBgImage(Image bgImage) {
this.bgImage = bgImage;
}
public void setFgImage(Image fgImage) {
this.fgImage = fgImage;
}
public Dimension getPreferredSize() {
return new Dimension(800, 600);
}
}
MyDataSource。java
public class MyDataSource {
public boolean hasData() {
return false;
}
}
TL;DR:看一下MyDisplay的末尾。java文件。你会看到我为了让它工作而插入的部分。请帮助我了解如何正确执行此操作
编辑:添加到MyDataSource中。java,根据安德鲁·汤普森的建议
# 1 楼答案
如果您不想在启动时看到空白屏幕,请仅在图像完全加载时显示帧。 可以在面板构造函数中加载图像
或者,如果您想要快速显示,请立即加载低清晰度图像,然后启动一个线程,在后台加载大图片,完成后在面板中进行设置
# 2 楼答案
试着从这样的事情中发展