有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java你能帮我指导这个Swing应用程序正确加载图像吗?

我是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文件。你会看到我为了让它工作而插入的部分。请帮助我了解如何正确执行此操作

编辑:添加到MyDataSource中。java,根据安德鲁·汤普森的建议


共 (2) 个答案

  1. # 1 楼答案

    如果您不想在启动时看到空白屏幕,请仅在图像完全加载时显示帧。 可以在面板构造函数中加载图像

    或者,如果您想要快速显示,请立即加载低清晰度图像,然后启动一个线程,在后台加载大图片,完成后在面板中进行设置

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