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

标签 java swing awt

我是 Java 新手,已经构建了一个简单的 Swing 应用程序,该应用程序以全屏模式运行,定期轮询数据源,并根据所述数据源显示不同的输出。我创建了一个简短的 MCVE展示我正在做的事情。

我的问题简而言之:我有一个应该始终显示的背景图像,以及一个仅在某些情况下显示的前景图像。不幸的是,它们第一次加载似乎需要几秒钟,这意味着屏幕是白色的,直到它们被加载并且屏幕被重新绘制。为了解决这个问题,我跟踪私有(private)成员的“周期”数量,并在开始时达到某些值,我强制它尝试绘制这些图像。然而,这感觉非常“hacky”,我更愿意学习在 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 文件的末尾。你会看到我为了让它工作而修改的部分。请帮助我了解如何正确执行此操作。

编辑:根据 Andrew Thompson 的建议添加到 MyDataSource.java 中。

最佳答案

尝试从这样的事情开始开发..

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

关于java - 你能帮助指导我让这个 Swing 应用程序正确加载图像吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27218443/

相关文章:

java - 如何使用 JTextArea 以及如何附加?

java - session.connection() 在 Hibernate 上已弃用?

java - 如果我增加内存堆是否会增加 GC 时间

Java 8 添加对象列表的多个属性的值

Java:透明 JPanel 上的 MouseEvent

java - JPanel 改变颜色以用鼠标绘制

java - 如何解决找不到 com.google.cloud.Service 的类文件

java - 如何在java中更改鼠标进入和鼠标退出时的字体颜色

java - 为什么 Graphics2D.setStoke() 对 Graphics2D.drawString 不起作用?

java - Java布局的对齐方式困惑