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();
}
}
}
我正在使用 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();
}
}
}