#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, см. раздел «Как создать экран-заставку» для получения более подробной информации, я стараюсь избегать этого (лично). Хотя это, безусловно, быстрее, это также так … неуклюжий (ИМХО)
Лично мне нравится использовать незакрашенное окно и просто делать то, что мне нужно, например…
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.добавить(текст); }