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;
            }

        }

    }
}