Graphics2D叠加图片+文字问题:文字有误

Graphics2D overlaying image + text problem: text is wrong

我正在使用 Graphics2D class 叠加两个图像(我希望一个用作背景,另一个较小的图像出现在顶部),然后我想添加一行简单的文本。这段代码效果很好,但我是从 for 循环中调用它的,在生成第一张图像后,其余的文本开始变得奇怪。我正在打印数字,就像程序在最后一张图片的文本上插入新文本一样。

这是我从 for 循环调用来创建图像的函数:

private static void createCompositeImage(BufferedImage image, BufferedImage overlay, String filename, String codigo) throws IOException {
        Graphics2D g = image.createGraphics();
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
        g.drawImage(overlay, (image.getWidth() - overlay.getWidth()),
                (image.getHeight() - overlay.getHeight())-200, null);

        g.setFont(g.getFont().deriveFont(40f));
        g.drawString("Entrada número: " + codigo, 30, image.getHeight()-300);
        g.dispose();

        ImageIO.write(image, "jpeg", new File(filename + ".jpeg"));

    }

这是在任何不是第一张图片上发生的情况:

有人知道我做错了什么吗?

绘制图形很像在现实世界中绘画canvas,您只是在已有的东西之上进行绘制。如果你想“替换”图像的一部分,你需要先在它的顶部绘画。

在这种情况下...

你可以...

在要绘制文本的区域上用默认颜色填充一个矩形。

这是有问题的,因为您需要知道可能覆盖的“最大”区域或之前绘制的内容的大小。

或者...

你可以...

从每个周期的空白开始。也就是说,从每个循环的“主”图像副本开始,然后简单地将状态重新绘制成。

例如...

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage master;
        private BufferedImage background;
        private Timer timer;

        private DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm:ss a");

        public TestPane() throws IOException {
            master = ImageIO.read(getClass().getResource("/images/background.jpg"));
            background = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
            renderBackground();
        }

        protected void renderBackground() {
            if (master == null) {
                return;
            }
            Graphics2D g2d = background.createGraphics();
            g2d.drawImage(master, 0, 0, this);

            g2d.setFont(getFont());
            FontMetrics fm = g2d.getFontMetrics();

            String time = LocalTime.now().format(timeFormatter);

            int x = (background.getWidth() - fm.stringWidth(time)) / 2;
            int y = ((background.getHeight() - fm.getHeight()) / 2) + fm.getAscent();

            g2d.drawString(time, x, y);

            g2d.dispose();

            repaint();
        }

        @Override
        public Dimension getPreferredSize() {
            if (master == null) {
                return new Dimension(200, 200);
            }

            return new Dimension(master.getWidth(), master.getHeight());
        }

        @Override
        public void addNotify() {
            super.addNotify();
            if (timer != null) {
                timer.stop();
            }
            timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    renderBackground();
                }
            });
            timer.start();
        }

        @Override
        public void removeNotify() {
            super.removeNotify();
            if (timer != null) {
                timer.stop();
            }
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background == null) {
                return;
            }
            Graphics2D g2d = (Graphics2D) g.create();
            int x = (getWidth() - background.getWidth()) / 2;
            int y = (getHeight() - background.getHeight()) / 2;
            g2d.drawImage(background, x, y, this);
            g2d.dispose();
        }

    }

}