【发布时间】:2021-06-05 13:04:32
【问题描述】:
我尝试了两种不同的方法来绘制相同的形状,第一个图像是通过覆盖 JPanel 的 paintComponent(Graphics g) 方法并使用 g.drawOval(..) 等绘制的, 第二个图像是通过创建一个缓冲图像并使用缓冲图像的图形在其上绘制来绘制的。如何在两种方法上实现相同的渲染质量?我尝试过使用许多不同的渲染提示,但没有一个提供相同的质量。我也试过用内核和过滤来锐化,还是不行。
private void createImage() {
image = new BufferedImage(IMG_SIZE, IMG_SIZE, BufferedImage.TYPE_INT_ARGB);
Graphics2D gr = image.createGraphics();
gr.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
gr.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
gr.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
//something along the way
gr.drawOval(.....);
gr.drawLine(.....);
gr.drawOval(.....);
panel.repaint();
gr.dispose();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(backgroundColor);
if (USE_BUFFERED_IMAGE) {
g.drawImage(image, startX, startY, null);
} else {
//something along the way
g.drawOval(.....);
g.drawLine(.....);
g.drawOval(.....);
}
}
Drawing using JPanel paintComponent graphics
Drawing using Buffered Image graphics then it is drawn on Jpanel via drawimage
编辑
我通过获取面板图形的几乎所有设置并将它们应用于缓冲图像图形来找到我的解决方案。不是仅使用相同的渲染提示或“最小可重现示例”方法。在这里,导入的事情是面板的图形将所有内容缩放 1.25,然后在面板上显示之前缩小到原始。
这是一个例子,-这不是我的代码的样子,这只是一个例子,给你一个想法-
private void createImages(Paint paint, RenderingHints hints,
AffineTransform transform, Stroke stroke,
Composite composite, GraphicsConfiguration config ){
image = config.createCompatibleImage(IMG_SIZE, IMG_SIZE,
BufferedImage.TYPE_INT_ARGB);
Graphics2D gr = image.createGraphics();
// same options
gr.setPaint(paint);
gr.setRenderingHints(hints);
gr.setTransform(transform);
gr.setStroke(stroke);
gr.setComposite(composite);
//something along the way
gr.drawOval(.....);
gr.drawLine(.....);
gr.drawOval(.....);
panel.repaint();
gr.dispose();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(backgroundColor);
if (USE_BUFFERED_IMAGE) {
Graphics2D g2 = (Graphics2D)g;
createImages(g2.getPaint(), g2.getRenderingHints(),g2.getTransform(),
g2.getStroke(),g2.getComposite(), g2.getDeviceConfiguration());
//scaling down is important because your drawings get scaled to 1.25
// by panels graphics' transformation
g.drawImage(image, startX, startY,(int)(IMG_SIZE*0.8),(int)(IMG_SIZE*0.8), null);
} else {
//something along the way
g.drawOval(.....);
g.drawLine(.....);
g.drawOval(.....);
}
}
【问题讨论】:
-
你不能在大多数情况下,特别是因为图像的大小是固定的,当在你的组件内部绘制时,它的大小可能会根据其父布局而变化,图像会被缩放,这会进一步降低质量。您可以尝试的一个愚蠢的想法是将图像的每个单独像素绘制为 1 x 1 矩形,并在您的绘图组件内使用指定的像素颜色。如果您的图像是静态的,虽然性能会很糟糕,但它可能值得吗?
-
首选方法是使用 JPanel paintComponent 方法在您的 GUI 上绘图。如果需要 BufferedImage,可以使用 JPanel printAll 方法创建一个。
-
我怎样才能在两种方法上实现相同的渲染质量? - 使用相同的渲染提示。例如,paintComponent() 方法默认不使用抗锯齿。因此,绘制到 BufferedImage 的 Graphics 看起来与在 paintComponent 中绘制的 Graphics 不同。发布一个适当的minimal reproducible example 来演示问题。首先只画一个椭圆,然后使用这两种方法让它工作相同。然后使绘画更复杂。这种方式更容易调试。此外,请勿在该绘制方法中更改组件的属性(背景)。
-
“使用相同的渲染提示”我的问题是我不知道 JPanel 中使用的渲染提示是什么。另外,正如我提到的,我尝试了许多渲染提示,但仍然无法获得相同的结果。
-
PrintAll 似乎可以解决我的问题,如果我可以管理我正在尝试做的事情,我会更新我的消息。我使用缓冲图像能够拖动图像而不需要每次都渲染复杂的绘图,这可能需要一些时间。
标签: java swing jpanel bufferedimage paintcomponent