BufferedImage有时候不会渲染

时间:2014-06-18 19:45:00

标签: java swing awt draw bufferedimage

我有一个类MenuScreen,我在其上绘制了很多图像。 (目前4 [对你来说可能不是很多,但对我而言])

只有一个呈现无论什么,有时它们是一半呈现,有时它们完全渲染,

有时它们根本不渲染(主要渲染仍在渲染)

这是我的代码

    public List<BufferedImage> im;

public MenuScreen() {
    setTitle("ALevelUp 0.0.1 Alpha");

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    initImages();
    JPanel p = new JPanel(new GridLayout(1, 1));

    p.add(new JLabel(new ImageIcon(im.get(0))));

    add(p);
    setSize(766, 500);
    setLocationRelativeTo(null);
    setVisible(true);
    System.err.println(getHeight() + "," + getWidth());

    Graphics2D g = (Graphics2D) im.get(0).getGraphics();
    draw(g);
}

public final void initImages() {
    im = a.init();
}

public final void draw(Graphics2D g) {
    BufferedImage s1 = im.get(1);
    Graphics2D s1g = (Graphics2D) s1.getGraphics();
    s1g.setFont(scale(a.getFont(), s1g, "Slot 1", s1));
    s1g.setColor(Color.black);
    s1g.drawString("Slot 1", s1.getWidth() / 2 - 23, s1.getHeight() / 2 + 7);
    g.drawImage(s1, (getWidth() / 2) - (s1.getWidth() / 2) - 21,
            47, rootPane);
    s1g.setColor(new Color(253, 198, 147));
    s1g.fillRect(106, 20, 100, 20);
    s1g.setColor(Color.black);
    s1g.drawString("Slot 2", s1.getWidth() / 2 - 23, s1.getHeight() / 2 + 7);
    g.drawImage(s1, getWidth() / 2 - s1.getWidth() / 2 - 21, 179, rootPane);
    s1g.setColor(new Color(253, 198, 147));
    s1g.fillRect(106, 20, 100, 20);
    s1g.setColor(Color.black);
    s1g.drawString("Slot 3", s1.getWidth() / 2 - 23, s1.getHeight() / 2 + 7);
    g.drawImage(s1, getWidth() / 2 - s1.getWidth() / 2 - 21, 311, rootPane);
}

public Font scale(Font f, Graphics g, String text, BufferedImage img) {
    float ntry = 20.0f;
    Font font = null;

    while (2 < 3) {
        font = f.deriveFont(ntry);
        FontMetrics fm = g.getFontMetrics(font);
        int width = fm.stringWidth(text);
        if (width < img.getWidth()) {
            return font;
        }
    }
}

任何人都可以帮助我理解为什么会发生这种情况以及我可以做些什么来解决它?

编辑:以下是图片资源,如果您需要它们:
The Main Screen
The Slot Panels
How it looks when it works

1 个答案:

答案 0 :(得分:4)

我必须修改大部分代码才能使某些东西起作用。我假设这就是你想要的。

enter image description here

以下是我所做的更改。

  1. 我添加了一个名为SwingUtilities invokeLater的main方法,将Swing组件放在Event Dispatch thread上。

  2. 我将代码分为3个类,DrawImage,DrawingPanel和Snippet。 DrawImage创建四个图像。 DrawingPanel将四个图像绘制到JPanel上。 Snippet创建JFrame并将绘图面板添加到JFrame。

  3. 我定义了绘图面板的大小以容纳4个插槽。我打包了JFrame JFrame将是用于保存绘图面板的正确尺寸。

  4. 我覆盖了paintComponent方法,从图像列表中绘制了四个图像。这些图像已经在DrawImage类中创建。我调用了super.paintComponent以确保正确绘制了所有Swing子组件。

  5. 我在创建Swing GUI之前创建了图像。

  6. 我使用了我创建的方法centerString来将文本居中放在图像中。我单独留下了缩放方法。

  7. 这是修改后的代码。与你的不同,它可以运行。

    package snippet;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.FontMetrics;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;
    import java.awt.font.FontRenderContext;
    import java.awt.geom.Rectangle2D;
    import java.awt.image.BufferedImage;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class Snippet implements Runnable {
    
        private JFrame frame;
    
        private List<BufferedImage> imageList;
    
        public Snippet() {
            imageList = new ArrayList<BufferedImage>();
            new DrawImage().createImages();
        }
    
        @Override
        public void run() {
            frame = new JFrame();
            frame.setTitle("ALevelUp 0.0.1 Alpha");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            DrawingPanel p = new DrawingPanel();
            frame.add(p);
    
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
    
            System.out.println(frame.getHeight() + "," + frame.getWidth());
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Snippet());
        }
    
        public class DrawingPanel extends JPanel {
    
            private static final long   serialVersionUID    = 
                    2535522354552193273L;
    
            public DrawingPanel() {
                this.setPreferredSize(new Dimension(550, 350));
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
    
                int x = 50;
                int y = 50;
    
                for (int i = 0; i < 2; i++) {
                    BufferedImage image = null;
                    for (int j = 0; j < 2; j++) {
                        image = imageList.get(i * 2 + j);
                        g.drawImage(image, x, y, this);
                        x += image.getWidth() + 50;
                    }
                    x = 50;
                    y += image.getHeight() + 50;
                }
            }
        }
    
        public class DrawImage {
    
            public void createImages() {
                imageList.add(createImage("Slot 1"));
                imageList.add(createImage("Slot 2"));
                imageList.add(createImage("Slot 3"));
                imageList.add(createImage("Slot 4"));
            }
    
            private BufferedImage createImage(String text) {
                Rectangle r = new Rectangle(0, 0, 200, 100);
                BufferedImage image = new BufferedImage(r.width, r.height,
                        BufferedImage.TYPE_INT_RGB);
    
                Graphics2D g = (Graphics2D) image.getGraphics();
                Font font = g.getFont();
                g.setFont(scale(font, g, text, image));
                g.setColor(Color.BLACK);
                g.fillRect(0, 0, image.getWidth(), image.getHeight());
                g.setColor(Color.YELLOW);
                centerString(g, r, text, font);
                g.dispose();
    
                return image;
            }
    
            private Font scale(Font f, Graphics g, String text, 
                    BufferedImage img) {
                float ntry = 20.0f;
                Font font = null;
    
                while (2 < 3) {
                    font = f.deriveFont(ntry);
                    FontMetrics fm = g.getFontMetrics(font);
                    int width = fm.stringWidth(text);
                    if (width < img.getWidth()) {
                        return font;
                    }
                }
            }
    
            /**
             * This method centers a <code>String</code> in
             * a bounding <code>Rectangle</code>.
             * @param g - The <code>Graphics</code> instance.
             * @param r - The bounding <code>Rectangle</code>.
             * @param s - The <code>String</code> to center in the
             * bounding rectangle.
             * @param font - The display font of the <code>String</code>
             *
             * @see java.awt.Graphics
             * @see java.awt.Rectangle
             * @see java.lang.String
             */
            private void centerString(Graphics g, Rectangle r, String s,
                    Font font) {
                FontRenderContext frc =
                        new FontRenderContext(null, true, true);
    
                Rectangle2D r2D = font.getStringBounds(s, frc);
                int rWidth = (int) Math.round(r2D.getWidth());
                int rHeight = (int) Math.round(r2D.getHeight());
                int rX = (int) Math.round(r2D.getX());
                int rY = (int) Math.round(r2D.getY());
    
                int a = (r.width / 2) - (rWidth / 2) - rX;
                int b = (r.height / 2) - (rHeight / 2) - rY;
    
                g.setFont(font);
                g.drawString(s, r.x + a, r.y + b);
            }
    
        }
    
    }