Java-在paintComponent中合成的圆角面板
根据原始问题(如下),我现在提供以下赏金: 基于Java-在paintComponent中合成的圆角面板,java,swing,rounded-corners,paintcomponent,compositing,Java,Swing,Rounded Corners,Paintcomponent,Compositing,根据原始问题(如下),我现在提供以下赏金: 基于AlphaComposite的圆角解决方案 请用JPanel演示 角落必须是完全透明的 必须能够支持JPG绘画,但仍有圆角 不得使用setClip(或任何剪辑) 必须有体面的表现 希望有人能很快学会,这似乎很容易 如果有一个很好的理由解释为什么这件事永远做不到,并且其他人也同意,我也会奖励奖金 下面是我想到的示例图像(但使用AlphaComposite) 原始问题 我一直在试图找到一种使用合成来实现圆角的方法,非常类似于或 但是,我在没有中间
AlphaComposite
的圆角解决方案
- 请用
演示李>JPanel
- 角落必须是完全透明的李>
- 必须能够支持JPG绘画,但仍有圆角
- 不得使用setClip(或任何剪辑)
- 必须有体面的表现
AlphaComposite
)
原始问题 我一直在试图找到一种使用合成来实现圆角的方法,非常类似于或 但是,我在没有中间BuffereImage的情况下尝试的结果是无效的——四舍五入的目标组合显然不会影响源。我尝试过不同的方法,但都不管用。应该是一个圆形的红色矩形,而不是正方形 所以,我有两个问题,真的: 1) 有没有办法让这一切顺利进行 2) 中间映像实际上会产生更好的性能吗 SSCCE: 测试面板t面板
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JLabel;
public class TPanel extends JLabel {
int w = 300;
int h = 200;
public TPanel() {
setOpaque(false);
setPreferredSize(new Dimension(w, h));
setMaximumSize(new Dimension(w, h));
setMinimumSize(new Dimension(w, h));
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
// Yellow is the clipped area.
g2d.setColor(Color.yellow);
g2d.fillRoundRect(0, 0, w, h, 20, 20);
g2d.setComposite(AlphaComposite.Src);
// Red simulates the image.
g2d.setColor(Color.red);
g2d.setComposite(AlphaComposite.SrcAtop);
g2d.fillRect(0, 0, w, h);
}
}
以及它的沙箱
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
public class Sandbox {
public static void main(String[] args) {
JFrame f = new JFrame();
f.setMinimumSize(new Dimension(800, 600));
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new FlowLayout());
TPanel pnl = new TPanel();
f.getContentPane().add(pnl);
f.setVisible(true);
}
}
我已经研究过这个问题,但无法在对系统类的单个调用中看到如何做到这一点 Graphics2D是一个抽象实例,实现为SunGraphics2D。例如,源代码可以在上获得,因此我们可以通过复制一些代码来“做相同的事情,但不同”。但是,绘制图像的方法取决于某些“管道”类,这些类不可用。虽然你做了一些关于类加载的事情,但是你可能会碰到一些本机的、优化的类,这些类不能被操作来实现理论上的最优方法;你所得到的只是把图像画成正方形 但是,我们可以采用一种方法,使我们自己的非本机(读:慢?)代码尽可能少地运行,并且不取决于图像大小,而是取决于圆形矩形中(相对)较低的区域。而且,不复制内存中的图像,会消耗大量内存。但是,如果您有大量内存,那么显然,在创建实例之后,缓存的映像会更快 备选案文1:
import java.awt.Composite;
import java.awt.CompositeContext;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import javax.swing.JLabel;
public class TPanel2 extends JLabel implements Composite, CompositeContext {
private int w = 300;
private int h = 200;
private int cornerRadius = 20;
private int[] roundRect; // first quadrant
private BufferedImage image;
private int[][] first = new int[cornerRadius][];
private int[][] second = new int[cornerRadius][];
private int[][] third = new int[cornerRadius][];
private int[][] forth = new int[cornerRadius][];
public TPanel2() {
setOpaque(false);
setPreferredSize(new Dimension(w, h));
setMaximumSize(new Dimension(w, h));
setMinimumSize(new Dimension(w, h));
// calculate round rect
roundRect = new int[cornerRadius];
for(int i = 0; i < roundRect.length; i++) {
roundRect[i] = (int)(Math.cos(Math.asin(1 - ((double)i)/20))*20); // x for y
}
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); // all black
}
@Override
public void paintComponent(Graphics g) {
// discussion:
// We have to work with the passed Graphics object.
if(g instanceof Graphics2D) {
Graphics2D g2d = (Graphics2D) g;
// draw the whole image and save the corners
g2d.setComposite(this);
g2d.drawImage(image, 0, 0, null);
} else {
super.paintComponent(g);
}
}
@Override
public CompositeContext createContext(ColorModel srcColorModel,
ColorModel dstColorModel, RenderingHints hints) {
return this;
}
@Override
public void dispose() {
}
@Override
public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
// lets assume image pixels >> round rect pixels
// lets also assume bulk operations are optimized
// copy current pixels
for(int i = 0; i < cornerRadius; i++) {
// quadrants
// from top to buttom
// first
first[i] = (int[]) dstOut.getDataElements(src.getWidth() - (cornerRadius - roundRect[i]), i, cornerRadius - roundRect[i], 1, first[i]);
// second
second[i] = (int[]) dstOut.getDataElements(0, i, cornerRadius - roundRect[i], 1, second[i]);
// from buttom to top
// third
third[i] = (int[]) dstOut.getDataElements(0, src.getHeight() - i - 1, cornerRadius - roundRect[i], 1, third[i]);
// forth
forth[i] = (int[]) dstOut.getDataElements(src.getWidth() - cornerRadius + roundRect[i], src.getHeight() - i - 1, cornerRadius - roundRect[i], 1, forth[i]);
}
// overwrite entire image as a square
dstOut.setRect(src);
// copy previous pixels back in corners
for(int i = 0; i < cornerRadius; i++) {
// first
dstOut.setDataElements(src.getWidth() - cornerRadius + roundRect[i], i, first[i].length, 1, second[i]);
// second
dstOut.setDataElements(0, i, second[i].length, 1, second[i]);
// third
dstOut.setDataElements(0, src.getHeight() - i - 1, third[i].length, 1, third[i]);
// forth
dstOut.setDataElements(src.getWidth() - cornerRadius + roundRect[i], src.getHeight() - i - 1, forth[i].length, 1, forth[i]);
}
}
}
导入java.awt.Composite;
导入java.awt.CompositeContext;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.RenderingHints;
导入java.awt.image.buffereImage;
导入java.awt.image.ColorModel;
导入java.awt.image.graster;
导入java.awt.image.WritableRaster;
导入javax.swing.JLabel;
公共类TPanel2扩展了JLabel,实现了复合的CompositeContext{
私人int w=300;
私有int h=200;
专用半径=20;
private int[]roundRect;//第一象限
私有缓冲图像;
private int[][]first=新int[cornerRadius][];
私有整数[][]秒=新整数[cornerRadius][];
私有int[]third=新int[cornerRadius][];
私有整数[][]第四=新整数[cornerRadius][];
公共TPanel2(){
设置不透明(假);
设置首选尺寸(新尺寸(w,h));
设置最大尺寸(新尺寸(w,h));
设置最小尺寸(新尺寸(w,h));
//计算圆矩形
roundRect=新整数[cornerRadius];
for(int i=0;i>圆形矩形像素
//我们还假设批量操作已优化
//复制当前像素
对于(int i=0;i
备选案文2:
import java.awt.AlphaComposite;
import java.awt.Composite;
import java.awt.CompositeContext;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import javax.swing.JLabel;
public class TPanel extends JLabel implements Composite, CompositeContext {
private int w = 300;
private int h = 200;
private int cornerRadius = 20;
private int[] roundRect; // first quadrant
private BufferedImage image;
private boolean initialized = false;
private int[][] first = new int[cornerRadius][];
private int[][] second = new int[cornerRadius][];
private int[][] third = new int[cornerRadius][];
private int[][] forth = new int[cornerRadius][];
public TPanel() {
setOpaque(false);
setPreferredSize(new Dimension(w, h));
setMaximumSize(new Dimension(w, h));
setMinimumSize(new Dimension(w, h));
// calculate round rect
roundRect = new int[cornerRadius];
for(int i = 0; i < roundRect.length; i++) {
roundRect[i] = (int)(Math.cos(Math.asin(1 - ((double)i)/20))*20); // x for y
}
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); // all black
}
@Override
public void paintComponent(Graphics g) {
if(g instanceof Graphics2D) {
Graphics2D g2d = (Graphics2D) g;
// draw 1 + 2 rectangles and copy pixels from image. could also be 1 rectangle + 4 edges
g2d.setComposite(AlphaComposite.Src);
g2d.drawImage(image, cornerRadius, 0, image.getWidth() - cornerRadius - cornerRadius, image.getHeight(), null);
g2d.drawImage(image, 0, cornerRadius, cornerRadius, image.getHeight() - cornerRadius - cornerRadius, null);
g2d.drawImage(image, image.getWidth() - cornerRadius, cornerRadius, image.getWidth(), image.getHeight() - cornerRadius, image.getWidth() - cornerRadius, cornerRadius, image.getWidth(), image.getHeight() - cornerRadius, null);
// draw the corners using our own logic
g2d.setComposite(this);
g2d.drawImage(image, 0, 0, null);
} else {
super.paintComponent(g);
}
}
@Override
public CompositeContext createContext(ColorModel srcColorModel,
ColorModel dstColorModel, RenderingHints hints) {
return this;
}
@Override
public void dispose() {
}
@Override
public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
// assume only corners need painting
if(!initialized) {
// copy image pixels
for(int i = 0; i < cornerRadius; i++) {
// quadrants
// from top to buttom
// first
first[i] = (int[]) src.getDataElements(src.getWidth() - cornerRadius, i, roundRect[i], 1, first[i]);
// second
second[i] = (int[]) src.getDataElements(cornerRadius - roundRect[i], i, roundRect[i], 1, second[i]);
// from buttom to top
// third
third[i] = (int[]) src.getDataElements(cornerRadius - roundRect[i], src.getHeight() - i - 1, roundRect[i], 1, third[i]);
// forth
forth[i] = (int[]) src.getDataElements(src.getWidth() - cornerRadius, src.getHeight() - i - 1, roundRect[i], 1, forth[i]);
}
initialized = true;
}
// copy image pixels into corners
for(int i = 0; i < cornerRadius; i++) {
// first
dstOut.setDataElements(src.getWidth() - cornerRadius, i, first[i].length, 1, second[i]);
// second
dstOut.setDataElements(cornerRadius - roundRect[i], i, second[i].length, 1, second[i]);
// third
dstOut.setDataElements(cornerRadius - roundRect[i], src.getHeight() - i - 1, third[i].length, 1, third[i]);
// forth
dstOut.setDataElements(src.getWidth() - cornerRadius, src.getHeight() - i - 1, forth[i].length, 1, forth[i]);
}
}
}
导入java.awt.AlphaComposite;
导入java.awt.Composite;
导入java.awt.CompositeContext;
导入java.awt.Dimens