Можете ли вы помочь мне правильно загрузить приложение Swing для загрузки изображений?

1

Я новичок в Java и создал простое приложение Swing, которое работает в полноэкранном режиме, постоянно проверяет источник данных с регулярными интервалами и показывает разные выходные данные в зависимости от указанного источника данных. Я создал короткий MCVE, чтобы продемонстрировать, что я делаю.

Моя проблема в двух словах: у меня есть фоновое изображение, которое должно всегда отображаться, и изображение переднего плана, которое должно отображаться только при определенных обстоятельствах. К сожалению, кажется, что им требуется всего несколько секунд для загрузки в первый раз, что означает, что экран белый, пока он не будет загружен, и экран будет перекрашен. Чтобы решить это, я отслеживаю количество "циклов" с частным членом и при определенных значениях к началу, я заставляю его пытаться рисовать эти изображения. Однако это кажется очень "взломанным", и я бы скорее научился правильно загружать и отображать изображения в приложениях 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. Вы увидите часть, в которую я взломал, чтобы она работала. Пожалуйста, помогите мне понять, как это сделать правильно.

EDIT: добавлено в MyDataSource.java, по предложению Эндрю Томпсона.

  • 0
    Используйте SwingWorker , например , для загрузки изображений при запуске.
  • 0
    1) UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); должно быть UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); .. 2) Для более быстрой помощи, опубликуйте MCVE ( пример минимальной полной проверки ) или SSCCE (короткий, самодостаточный , правильный пример).
Показать ещё 9 комментариев
Теги:
swing
awt

2 ответа

2
Лучший ответ

Попробуйте развиться из чего-то вроде этого..

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

Если вы не хотите видеть пустой экран при запуске, покажите Frame только тогда, когда изображения полностью загружены. Вы можете загрузить изображение в конструкторе Panel

Или, если вы хотите быстро отобразить, сразу загрузите изображение с низким разрешением, а затем запустите Thread, который загрузит большое изображение в фоновом режиме, и установите его на панели, когда закончите.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню