我是 Java 新手,已经构建了一个简单的 Swing 应用程序,该应用程序以全屏模式运行,定期轮询数据源,并根据所述数据源显示不同的输出。我创建了一个简短的 MCVE展示我正在做的事情。
我的问题简而言之:我有一个应该始终显示的背景图像,以及一个仅在某些情况下显示的前景图像。不幸的是,它们第一次加载似乎需要几秒钟,这意味着屏幕是白色的,直到它们被加载并且屏幕被重新绘制。为了解决这个问题,我跟踪私有(private)成员的“周期”数量,并在开始时达到某些值,我强制它尝试绘制这些图像。然而,这感觉非常“hacky”,我更愿意学习在 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 文件的末尾。你会看到我为了让它工作而修改的部分。请帮助我了解如何正确执行此操作。
编辑:根据 Andrew Thompson 的建议添加到 MyDataSource.java 中。
最佳答案
尝试从这样的事情开始开发..
import java.awt.Component;
import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
public class Main {
public static void main(String[] args) throws IOException {
JFrame frame = new JFrame("FullScreen Demo");
frame.setUndecorated(true);
frame.add(new Component() {
BufferedImage bg = ImageIO.read(new URL("http://upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Neige_dans_le_djebel_Ch%C3%A9lia.JPG/1920px-Neige_dans_le_djebel_Ch%C3%A9lia.JPG"));
BufferedImage fg = ImageIO.read(new URL("http://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/W1769-Vallet_BMX_N_82131.JPG/1920px-W1769-Vallet_BMX_N_82131.JPG"));
@Override
public void paint(Graphics g) {
super.paint(g);
g.drawImage(bg, 0, 0, getWidth(), getHeight(), this);
g.drawImage(fg, 50, 50, getWidth()/10, getHeight()/10, this);
}
});
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();
gs.setFullScreenWindow(frame);
frame.validate();
}
}
关于java - 你能帮助指导我让这个 Swing 应用程序正确加载图像吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27218443/