Ho esaminato questo problema e non si può vedere come fare questo in un chiamata singola alle classi di sistema.
Graphics2D è un'istanza astratta, implementata come SunGraphics2D. Il codice sorgente è disponibile per esempio docjar e quindi potremmo potenzialmente "fare lo stesso, ma diverso" copiando un po 'di codice. Tuttavia, i metodi per dipingere un'immagine dipendono da alcune classi "pipe" che non sono disponibili. Anche se fai roba con il caricamento di classe, probabilmente colpirai una classe nativa ottimizzata che non può essere manipolata per fare l'approccio teoricamente ottimale; tutto quello che ottieni è dipingere le immagini come quadrati.
Tuttavia possiamo creare un approccio in cui il nostro codice, non nativo (leggi: lento?), Esegue il codice il meno possibile, e non in base alla dimensione dell'immagine ma piuttosto alla (relativamente) bassa area del round rett. Inoltre, senza copiare le immagini in memoria, consumando molta memoria. Ma se hai molta memoria, ovviamente, un'immagine cache è più veloce dopo che l'istanza è stata creata.
Alternativa 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]);
}
}
}
Alternativa 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]);
}
}
}
Spero che questo aiuti, questo è un po 'di un secondo migliore soluzione, ma questa è la vita (questo è quando un po' di grafica-guru viene e mi dimostra sbagliato (??) ..) ;-)
si prega di leggere domande su [JButton e grafica] (http://stackoverflow.com/users/584862/mre?tab=questions) di @mre – mKorbel
ti riferisci http://stackoverflow.com/questions/8416295/component-pittura-fuori-custom-border? Questo riguarda i colori pieni riempiti nella grafica, non le immagini ... Sto cercando un modo per usare una forma composita per impostare una maschera, quindi dipingere un'immagine sopra di essa. – Ben