JScrollPanel内部的Java2D图形;结果不太好
我是荷兰计算机科学专业的学生,我正在做一项作业,在这项作业中我必须画几个形状。为了使这些形状看起来更好,我启用了“渲染提示抗锯齿”。但现在我的问题是,当我用我的JScrollPanel滚动到图形不在屏幕上的位置,然后向后滚动时,似乎抗锯齿和透明度没有正常工作 在下面链接的图片中,我已经滚动到形状的一半,然后又滚动回来 我真的不知道问题在哪里,所以我提供了下面这个类的完整代码 我想提前谢谢你 米兰v。迪克JScrollPanel内部的Java2D图形;结果不太好,java,swing,rendering,jscrollpane,java-2d,Java,Swing,Rendering,Jscrollpane,Java 2d,我是荷兰计算机科学专业的学生,我正在做一项作业,在这项作业中我必须画几个形状。为了使这些形状看起来更好,我启用了“渲染提示抗锯齿”。但现在我的问题是,当我用我的JScrollPanel滚动到图形不在屏幕上的位置,然后向后滚动时,似乎抗锯齿和透明度没有正常工作 在下面链接的图片中,我已经滚动到形状的一半,然后又滚动回来 我真的不知道问题在哪里,所以我提供了下面这个类的完整代码 我想提前谢谢你 米兰v。迪克 import java.awt.*; import java.awt.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;
import javax.imageio.ImageIO;
import javax.swing.*;
@SuppressWarnings("serial")
public class AgendaPanel extends JPanel{
private final int WIDTH = 24; // width in hours
private final Color BUTTON_TOP_GRADIENT = new Color(250, 250, 250);
private final Color BUTTON_BOTTOM_GRADIENT = new Color(210, 210, 210);
private ArrayList<Line> lines = new ArrayList<Line>();
private ArrayList<Shape> shadowBoxes = new ArrayList<Shape>();
private ArrayList<Shape> itemBoxes = new ArrayList<Shape>();
private ArrayList<Image2D> images = new ArrayList<Image2D>();
private ArrayList<String2D> names = new ArrayList<String2D>();
public AgendaPanel(){
setPreferredSize(new Dimension(WIDTH*100, 300));
drawGrid();
}
public void drawGrid(){
for(int i=100; i < WIDTH*100; i+=100){
lines.add(new Line(i,0,i,300,Color.GRAY));
}
for(int i=50; i < WIDTH*100; i+=100){
lines.add(new Line(i,0,i,300, Color.LIGHT_GRAY));
}
// change to the amount of podia
for(int i=75; i < 300; i+=75){
lines.add(new Line(0, i, WIDTH*100, i, Color.black));
}
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
RenderingHints qualityHints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON );
qualityHints.put(
RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY );
g2.setRenderingHints( qualityHints );
// Add agenda items to the draw queue
addAgendaItem("logo.png", "Minus Militia", 2, 2, 170);
//draw time grid
for(Line line : lines){
g2.setColor(line.color);
g2.drawLine(line.x1, line.y1, line.x2, line.y2);
}
//Shape roundRect = new RoundRectangle2D.Double(2, 2, 170, 71, 20, 20);
//Paint all shadow shapes as the first layer over the grid with a transparacy of 30%
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.3f));
for (Shape shadow : shadowBoxes){
paintBorderShadow(g2,4,shadow);
}
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,1f));
//Paint all boxes as second layer over the shadows
g2.setStroke(new BasicStroke());
g2.setPaint(new GradientPaint( new Point(0, 0),
BUTTON_TOP_GRADIENT,
new Point(0, 71),
BUTTON_BOTTOM_GRADIENT));
for (Shape box : itemBoxes){
g2.fill(box);
}
// Paint as third layer all the images over the boxes
for (Image2D image : images){
g2.drawImage(image.getImage() , image.getX(), image.getY(), null);
}
g2.setColor(Color.black);
//Paint all names as fourth and last layer
for (String2D name : names){
g2.drawString(name.getText(), name.getX(), name.getY());
}
}
private void addAgendaItem(String imageFile,String name, int x, int y, int length){
shadowBoxes.add(new RoundRectangle2D.Double(x+3, y+3, length-3, 68, 20, 20));
itemBoxes.add(new RoundRectangle2D.Double(x, y, length, 71, 20, 20));
BufferedImage in = null;
try {
in = ImageIO.read(new File("logo.png"));
} catch (IOException e) {
e.printStackTrace();
}
images.add(new Image2D(x+8, y+8 ,drawPicture(scaleImage(in, 55, 55,Color.black),20)));
names.add(new String2D(x+73,y+38, name));
}
private BufferedImage drawPicture(BufferedImage image, int cornerRadius){
int w = image.getWidth();
int h = image.getHeight();
BufferedImage output = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = output.createGraphics();
g2.setComposite(AlphaComposite.Src);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.WHITE);
g2.fill(new RoundRectangle2D.Float(0, 0, w, h, cornerRadius, cornerRadius));
g2.setComposite(AlphaComposite.SrcAtop);
g2.drawImage(image, 0, 0, null);
g2.dispose();
return output;
}
public BufferedImage scaleImage(BufferedImage img, int width, int height, Color background) {
int imgWidth = img.getWidth();
int imgHeight = img.getHeight();
if (imgWidth*height < imgHeight*width) {
width = imgWidth*height/imgHeight;
} else {
height = imgHeight*width/imgWidth;
}
BufferedImage output = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = output.createGraphics();
try {
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setBackground(background);
g.clearRect(0, 0, width, height);
g.drawImage(img, 0, 0, width, height, null);
} finally {
g.dispose();
}
return output;
}
private void paintBorderShadow(Graphics2D g2, int shadowWidth, Shape shape) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int sw = shadowWidth*2;
for (int i=sw; i >= 2; i-=2) {
float pct = (float)(sw - i) / (sw - 1);
g2.setColor(getMixedColor(Color.DARK_GRAY, pct,
Color.DARK_GRAY, 1.0f-pct));
g2.setStroke(new BasicStroke(i));
g2.draw(shape);
}
}
private static Color getMixedColor(Color c1, float pct1, Color c2, float pct2) {
float[] clr1 = c1.getComponents(null);
float[] clr2 = c2.getComponents(null);
for (int i = 0; i < clr1.length; i++) {
clr1[i] = (clr1[i] * pct1) + (clr2[i] * pct2);
}
return new Color(clr1[0], clr1[1], clr1[2], clr1[3]);
}
}
经过一番个人的深思熟虑之后,我发现了我的问题所在。我正在调整大小,并在每次重新绘制时为图像提供圆角。这以某种方式改变了g2对象,禁用了我的渲染。我已经把这段代码放到构造函数中,现在一切都顺利运行了 以下代码就是问题所在:
private BufferedImage drawPicture(BufferedImage image, int cornerRadius){
int w = image.getWidth();
int h = image.getHeight();
BufferedImage output = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = output.createGraphics();
g2.setComposite(AlphaComposite.Src);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.WHITE);
g2.fill(new RoundRectangle2D.Float(0, 0, w, h, cornerRadius, cornerRadius));
g2.setComposite(AlphaComposite.SrcAtop);
g2.drawImage(image, 0, 0, null);
g2.dispose();
return output;
}
public BufferedImage scaleImage(BufferedImage img, int width, int height, Color background) {
int imgWidth = img.getWidth();
int imgHeight = img.getHeight();
if (imgWidth*height < imgHeight*width) {
width = imgWidth*height/imgHeight;
} else {
height = imgHeight*width/imgWidth;
}
BufferedImage output = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = output.createGraphics();
try {
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setBackground(background);
g.clearRect(0, 0, width, height);
g.drawImage(img, 0, 0, width, height, null);
} finally {
g.dispose();
}
return output;
}
这是哪种方法:
private void addAgendaItem(String imageFile,String name, int x, int y, int length){
shadowBoxes.add(new RoundRectangle2D.Double(x+3, y+3, length-3, 68, 20, 20));
itemBoxes.add(new RoundRectangle2D.Double(x, y, length, 71, 20, 20));
BufferedImage in = null;
try {
in = ImageIO.read(new File("logo.png"));
} catch (IOException e) {
e.printStackTrace();
}
images.add(new Image2D(x+8, y+8 ,drawPicture(scaleImage(in, 55, 55,Color.black),20)));
names.add(new String2D(x+73,y+38, name));
}
这将调用上述两种方法(每次重新绘制),这是导致性能和绘图问题的原因。这是一种方法,有时可能会提高CPU效率(以及内存消耗),但是,这解决了问题 问题的存在是因为您正在更改作为“paintComponent”方法参数提供的图形对象的状态。这是一个常见的错误,它会导致各种奇怪的图形错误 您不应该更改对象的状态的原因是,该对象正由其父组件传递给您的组件,而父组件是从其父组件获取该对象的,依此类推。链中的每个组件(从右到所属窗口)都使用相同的图形对象来绘制自身。同样的图形对象也将自动传递给组件的任何子级。这是Swing工作原理的基础(与AWT甚至SWT相比,Swing工作原理的讨论是完全不同的主题) 相反,你应该做的是保护国家。这可以通过以下两种方式之一实现:
什么是Line、String2D和Image2D?这些是我用来存储要绘制的图像和字符串的2D信息的小类。我已经在描述中添加了代码。如果您要发布一个示例,请使用main方法将其作为一个工作示例,这样我们就可以自己运行它,而无需编写代码。感谢您的反馈,我已经将eclipse项目文件夹添加为可下载的zip文件。要更快地获得更好的帮助,请发布一个(经过测试且可读性最低的示例)。它应该是:一个源文件(可能包含多个类),有导入,有一个
main(string[])
将其放在屏幕上。。
addAgendaItem("logo.png", "Minus Militia", 2, 2, 170);
private void addAgendaItem(String imageFile,String name, int x, int y, int length){
shadowBoxes.add(new RoundRectangle2D.Double(x+3, y+3, length-3, 68, 20, 20));
itemBoxes.add(new RoundRectangle2D.Double(x, y, length, 71, 20, 20));
BufferedImage in = null;
try {
in = ImageIO.read(new File("logo.png"));
} catch (IOException e) {
e.printStackTrace();
}
images.add(new Image2D(x+8, y+8 ,drawPicture(scaleImage(in, 55, 55,Color.black),20)));
names.add(new String2D(x+73,y+38, name));
}