Заставка Jframe не будет отображать изображение

#java #swing #jframe #splash-screen

Вопрос:

Кажется, я не могу добавить изображение в JFRAME при запуске, он открывает заставку и отображает панель загрузки и текст, но изображения нет, изображение находится в том же месте, что и код. Путь к изображению в порядке, так как он не нужен, и при наведении курсора он отображает изображение в моей среде разработки, любая помощь была бы потрясающей.

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

}

Комментарии:

1. class.java (исходные) файлы иногда хранятся в другом каталоге, чем class.class (объектные) файлы. Вы не проверяете ошибки при чтении файла Calc.png. Создайте папку ресурсов для своего проекта и поместите свои изображения в папку ресурсов. У Oracle есть учебник, как создать заставку .

2. 🤔Где в вашем коде вы делаете f.add(image) ? Я бы также настоятельно рекомендовал не использовать null макеты и runningBar потенциально блокировать поток отправки событий, из-за чего он будет выглядеть так, как будто ваш пользовательский интерфейс «завис» и не будет реагировать, и добавьте к этому, что Swing небезопасен для потоков, и у вас есть еще одна проблема, с которой нужно разобраться

Ответ №1:

Итак, непосредственная проблема, которую я вижу, заключается в том, что вы на самом деле не добавляете image в свой фрейм.

Вам также нужно остерегаться ограничений ImageIcon . В вашем случае он ожидает найти изображение с именем Calc.png в текущем рабочем каталоге, проблема в том, что рабочий каталог может измениться.

Лучшим решением является «встраивание» этих ресурсов. Как это делается, обычно зависит от используемой вами среды разработки и системы сборки, но предполагается, что изображение окажется в пути к классу запущенного приложения, обычно включенного в JAR.

Но есть целый ряд других проблем, которые вам не помогут.

Качели небезопасны для резьбы и являются однопоточными. Это означает, что вы не должны обновлять пользовательский интерфейс (или любое состояние, на которое полагается пользовательский интерфейс) вне контекста потока диспетчеризации событий, и вы также не должны выполнять какие-либо длительные операции в контексте потока диспетчеризации событий.

Дополнительные сведения см. в разделе Параллелизм в Swing.

Это оставляет вас с проблемой. Как вы работаете, не блокируя пользовательский интерфейс, и поддерживаете его в актуальном состоянии? Ну, смотрите Рабочие потоки и SwingWorker для наиболее распространенного решения.

Хотя вы можете использовать встроенную поддержку экрана-заставки Java, см. раздел «Как создать экран-заставку» для получения более подробной информации, я стараюсь избегать этого (лично). Хотя это, безусловно, быстрее, это также так … неуклюжий (ИМХО)

Лично мне нравится использовать незакрашенное окно и просто делать то, что мне нужно, например…

Загрузка ОС Sith

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

        }

    }
}
 

Комментарии:

1. Спасибо, все решено!

2. изображение добавляется с помощью f.image — это было в исходном коде SplashScreen() { CreateGui(); addImage(); addText(); addProgressBar(); addMessage(); runningPBar(); f.добавить(изображение); f.добавить(панель прогресса); f.добавить(сообщение); f.добавить(текст); }