Jframe 启动画面不会显示图像
Jframe Splash screen wont display an image
我似乎无法在 运行 时向 JFRAME 添加图像,它会打开启动画面并显示加载栏和文本,但没有图像,图像与代码位于同一位置.图片路径很好,因为 none 需要,当鼠标悬停时,它会在我的 IDE 中显示图片,任何帮助都会很棒。
import javax.swing.*;
import java.awt.*;
public class SplashScreen {
public static void main(String[] args) {
new SplashScreen();
new MenuGui();
}
JFrame f;
JLabel image = new JLabel(new ImageIcon("Calc.png"));
JLabel text = new JLabel("Loading...");
JProgressBar progressBar = new JProgressBar();
JLabel message = new JLabel();
SplashScreen() {
CreateGui();
addImage();
addText();
addProgressBar();
addMessage();
runningPBar();
f.add(image);
f.add(progressBar);
f.add(message);
f.add(text);
}
public void CreateGui() {
f = new JFrame();
f.getContentPane().setLayout(null);
f.setUndecorated(true);
f.setSize(600, 600);
f.setLocationRelativeTo(null);
f.getContentPane().setBackground(Color.CYAN);
f.setVisible(true);
}
public void addText(){
text.setFont(new Font("arial",Font.BOLD,30));
text.setBounds(170,220,600,40);
text.setForeground(Color.black);
f.add(text);
}
public void addImage(){
image.setBounds(20,30,200,300);
image.setSize(600,200);
}
public void addMessage(){
message.setBounds(100, 280, 400, 30);
message.setForeground(Color.BLACK);
message.setFont(new Font("arial", Font.BOLD, 15));
f.add(message);
}
public void addProgressBar(){
progressBar.setBounds(100,280,400,30);
progressBar.setBorderPainted(true);
progressBar.setStringPainted(true);
progressBar.setForeground(Color.black);
progressBar.setBackground(Color.WHITE);
progressBar.setValue(0);
f.add(progressBar);
}
public void runningPBar(){
int i = 0;
while (i <=100){
try {
Thread.sleep(50);
progressBar.setValue(i);
message.setText("LOADING" + Integer.toString(i) + "%");
i++;
if(i == 100)
f.dispose();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
所以,我能看到的直接问题是您实际上并没有将 image
添加到您的框架中。
您还需要注意 ImageIcon
的限制。在你的例子中,它期望在当前工作目录中找到一个名为 Calc.png
的图像,问题是工作目录可以改变。
更好的解决办法是“嵌入”这些资源。这是如何完成的通常归结为您正在使用的 IDE 和构建系统,但目的是图像将最终位于 运行 应用程序的 class 路径中,通常包含在 JAR 中。
但是还有许多其他问题对您没有帮助。
Swing 不是线程安全的并且是单线程的。这意味着您不应该从事件调度线程的上下文之外更新 UI(或 UI 所依赖的任何状态),并且您不应该执行任何长时间的 运行 操作在事件调度线程的上下文中。
有关详细信息,请参阅 Concurrency in Swing。
这给你留下了一个问题。您是如何工作的,既不阻塞 UI,又让 UI 保持最新?好吧,请参阅 Worker Threads and SwingWorker 了解最常见的解决方案。
虽然您可以使用 Java 的内置启动画面支持,但请参阅 How to Create a Splash Screen 了解更多详细信息,我倾向于避免使用它(个人)。虽然它肯定更快,但它也……笨重(恕我直言)
就个人而言,我喜欢使用未修饰的 window 并且只做我需要做的,例如...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.color.ColorSpace;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
JFrame frame = new JFrame();
frame.setUndecorated(true);
SplashPane splashPane = new SplashPane();
splashPane.setSplashListener(new SplashListener() {
@Override
public void didCompleteLoading(SplashPane source) {
frame.dispose();
}
});
frame.add(splashPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public interface SplashListener {
public void didCompleteLoading(SplashPane source);
}
public class SplashPane extends JPanel {
private BufferedImage coloredImage;
private BufferedImage grayscaleImage;
private JLabel loadingLabel;
private JLabel tagLine;
private LoadingWorker loadingWorker;
private double progress = 0;
private SplashListener splashListener;
public SplashPane() throws IOException {
coloredImage = ImageIO.read(getClass().getResource("/images/SplashScreen.jpeg"));
ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
grayscaleImage = op.filter(coloredImage, null);
loadingLabel = new JLabel("Loading Sith OS");
tagLine = new JLabel("Your lack of faith is disturbing");
Font font = loadingLabel.getFont();
Font extraLargeFont = font.deriveFont(Font.BOLD, font.getSize() * 4);
Font largeFont = font.deriveFont(Font.BOLD, font.getSize() * 2);
loadingLabel.setFont(extraLargeFont);
loadingLabel.setForeground(Color.WHITE);
tagLine.setFont(largeFont);
tagLine.setForeground(Color.WHITE);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(20, 20, 20, 20);
gbc.anchor = GridBagConstraints.NORTH;
gbc.weightx = 1;
gbc.weighty = 0.5;
add(loadingLabel, gbc);
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.SOUTH;
add(tagLine, gbc);
configureLoadingWorker();
}
public void setSplashListener(SplashListener listener) {
splashListener = listener;
}
protected void configureLoadingWorker() {
loadingWorker = new LoadingWorker();
loadingWorker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (loadingWorker.getState() == SwingWorker.StateValue.DONE) {
progress = 1.0;
repaint();
// Because it's nice to see that last little bit of progress
Timer timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (splashListener != null) {
splashListener.didCompleteLoading(SplashPane.this);
}
}
});
timer.setRepeats(false);
timer.start();
} else if ("progress".equals(evt.getPropertyName())) {
progress = loadingWorker.getProgress() / 100.0;
repaint();
}
}
});
}
@Override
public void addNotify() {
super.addNotify();
loadingWorker.execute();
}
@Override
public void removeNotify() {
super.removeNotify();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(coloredImage.getWidth(), coloredImage.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int xPos = (getWidth() - coloredImage.getWidth()) / 2;
int yPos = (getHeight() - coloredImage.getHeight()) / 2;
g2d.drawImage(grayscaleImage, xPos, yPos, this);
int targetHeight = (int) (coloredImage.getHeight() * progress);
if (targetHeight > 0) {
BufferedImage subimage = coloredImage.getSubimage(0, coloredImage.getHeight() - targetHeight, coloredImage.getWidth(), targetHeight);
xPos = (getWidth() - coloredImage.getWidth()) / 2;
yPos = ((getHeight() - coloredImage.getHeight()) / 2) + (coloredImage.getHeight() - targetHeight);
g2d.drawImage(subimage, xPos, yPos, this);
}
g2d.dispose();
}
protected class LoadingWorker extends SwingWorker<Void, Void> {
@Override
protected Void doInBackground() throws Exception {
Random rnd = new Random();
int progress = 0;
Thread.sleep(2);
do {
int delta = rnd.nextInt(9) + 1;
progress += delta;
setProgress(progress);
Thread.sleep(500);
} while (progress < 100);
setProgress(100);
return null;
}
}
}
}
我似乎无法在 运行 时向 JFRAME 添加图像,它会打开启动画面并显示加载栏和文本,但没有图像,图像与代码位于同一位置.图片路径很好,因为 none 需要,当鼠标悬停时,它会在我的 IDE 中显示图片,任何帮助都会很棒。
import javax.swing.*;
import java.awt.*;
public class SplashScreen {
public static void main(String[] args) {
new SplashScreen();
new MenuGui();
}
JFrame f;
JLabel image = new JLabel(new ImageIcon("Calc.png"));
JLabel text = new JLabel("Loading...");
JProgressBar progressBar = new JProgressBar();
JLabel message = new JLabel();
SplashScreen() {
CreateGui();
addImage();
addText();
addProgressBar();
addMessage();
runningPBar();
f.add(image);
f.add(progressBar);
f.add(message);
f.add(text);
}
public void CreateGui() {
f = new JFrame();
f.getContentPane().setLayout(null);
f.setUndecorated(true);
f.setSize(600, 600);
f.setLocationRelativeTo(null);
f.getContentPane().setBackground(Color.CYAN);
f.setVisible(true);
}
public void addText(){
text.setFont(new Font("arial",Font.BOLD,30));
text.setBounds(170,220,600,40);
text.setForeground(Color.black);
f.add(text);
}
public void addImage(){
image.setBounds(20,30,200,300);
image.setSize(600,200);
}
public void addMessage(){
message.setBounds(100, 280, 400, 30);
message.setForeground(Color.BLACK);
message.setFont(new Font("arial", Font.BOLD, 15));
f.add(message);
}
public void addProgressBar(){
progressBar.setBounds(100,280,400,30);
progressBar.setBorderPainted(true);
progressBar.setStringPainted(true);
progressBar.setForeground(Color.black);
progressBar.setBackground(Color.WHITE);
progressBar.setValue(0);
f.add(progressBar);
}
public void runningPBar(){
int i = 0;
while (i <=100){
try {
Thread.sleep(50);
progressBar.setValue(i);
message.setText("LOADING" + Integer.toString(i) + "%");
i++;
if(i == 100)
f.dispose();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
所以,我能看到的直接问题是您实际上并没有将 image
添加到您的框架中。
您还需要注意 ImageIcon
的限制。在你的例子中,它期望在当前工作目录中找到一个名为 Calc.png
的图像,问题是工作目录可以改变。
更好的解决办法是“嵌入”这些资源。这是如何完成的通常归结为您正在使用的 IDE 和构建系统,但目的是图像将最终位于 运行 应用程序的 class 路径中,通常包含在 JAR 中。
但是还有许多其他问题对您没有帮助。
Swing 不是线程安全的并且是单线程的。这意味着您不应该从事件调度线程的上下文之外更新 UI(或 UI 所依赖的任何状态),并且您不应该执行任何长时间的 运行 操作在事件调度线程的上下文中。
有关详细信息,请参阅 Concurrency in Swing。
这给你留下了一个问题。您是如何工作的,既不阻塞 UI,又让 UI 保持最新?好吧,请参阅 Worker Threads and SwingWorker 了解最常见的解决方案。
虽然您可以使用 Java 的内置启动画面支持,但请参阅 How to Create a Splash Screen 了解更多详细信息,我倾向于避免使用它(个人)。虽然它肯定更快,但它也……笨重(恕我直言)
就个人而言,我喜欢使用未修饰的 window 并且只做我需要做的,例如...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.color.ColorSpace;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
JFrame frame = new JFrame();
frame.setUndecorated(true);
SplashPane splashPane = new SplashPane();
splashPane.setSplashListener(new SplashListener() {
@Override
public void didCompleteLoading(SplashPane source) {
frame.dispose();
}
});
frame.add(splashPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public interface SplashListener {
public void didCompleteLoading(SplashPane source);
}
public class SplashPane extends JPanel {
private BufferedImage coloredImage;
private BufferedImage grayscaleImage;
private JLabel loadingLabel;
private JLabel tagLine;
private LoadingWorker loadingWorker;
private double progress = 0;
private SplashListener splashListener;
public SplashPane() throws IOException {
coloredImage = ImageIO.read(getClass().getResource("/images/SplashScreen.jpeg"));
ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
grayscaleImage = op.filter(coloredImage, null);
loadingLabel = new JLabel("Loading Sith OS");
tagLine = new JLabel("Your lack of faith is disturbing");
Font font = loadingLabel.getFont();
Font extraLargeFont = font.deriveFont(Font.BOLD, font.getSize() * 4);
Font largeFont = font.deriveFont(Font.BOLD, font.getSize() * 2);
loadingLabel.setFont(extraLargeFont);
loadingLabel.setForeground(Color.WHITE);
tagLine.setFont(largeFont);
tagLine.setForeground(Color.WHITE);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(20, 20, 20, 20);
gbc.anchor = GridBagConstraints.NORTH;
gbc.weightx = 1;
gbc.weighty = 0.5;
add(loadingLabel, gbc);
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.SOUTH;
add(tagLine, gbc);
configureLoadingWorker();
}
public void setSplashListener(SplashListener listener) {
splashListener = listener;
}
protected void configureLoadingWorker() {
loadingWorker = new LoadingWorker();
loadingWorker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (loadingWorker.getState() == SwingWorker.StateValue.DONE) {
progress = 1.0;
repaint();
// Because it's nice to see that last little bit of progress
Timer timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (splashListener != null) {
splashListener.didCompleteLoading(SplashPane.this);
}
}
});
timer.setRepeats(false);
timer.start();
} else if ("progress".equals(evt.getPropertyName())) {
progress = loadingWorker.getProgress() / 100.0;
repaint();
}
}
});
}
@Override
public void addNotify() {
super.addNotify();
loadingWorker.execute();
}
@Override
public void removeNotify() {
super.removeNotify();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(coloredImage.getWidth(), coloredImage.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int xPos = (getWidth() - coloredImage.getWidth()) / 2;
int yPos = (getHeight() - coloredImage.getHeight()) / 2;
g2d.drawImage(grayscaleImage, xPos, yPos, this);
int targetHeight = (int) (coloredImage.getHeight() * progress);
if (targetHeight > 0) {
BufferedImage subimage = coloredImage.getSubimage(0, coloredImage.getHeight() - targetHeight, coloredImage.getWidth(), targetHeight);
xPos = (getWidth() - coloredImage.getWidth()) / 2;
yPos = ((getHeight() - coloredImage.getHeight()) / 2) + (coloredImage.getHeight() - targetHeight);
g2d.drawImage(subimage, xPos, yPos, this);
}
g2d.dispose();
}
protected class LoadingWorker extends SwingWorker<Void, Void> {
@Override
protected Void doInBackground() throws Exception {
Random rnd = new Random();
int progress = 0;
Thread.sleep(2);
do {
int delta = rnd.nextInt(9) + 1;
progress += delta;
setProgress(progress);
Thread.sleep(500);
} while (progress < 100);
setProgress(100);
return null;
}
}
}
}