2
我在我的swing應用程序中使用了Nimbus外觀和感覺,它非常酷。
我注意到它是一個「純粹」的外觀和感覺:它「皮膚」組件,但不添加新的圖形元素。
我不知道它的渲染技術的某些部分是可重複使用的,例如類:
swing nimbus ShadowEffect
javax.swing.plaf.nimbus.ShadowEffect
可添加陰影像JLabel的其他元素,即在默認情況下沒有影子?
我在我的swing應用程序中使用了Nimbus外觀和感覺,它非常酷。
我注意到它是一個「純粹」的外觀和感覺:它「皮膚」組件,但不添加新的圖形元素。
我不知道它的渲染技術的某些部分是可重複使用的,例如類:
swing nimbus ShadowEffect
javax.swing.plaf.nimbus.ShadowEffect
可添加陰影像JLabel的其他元素,即在默認情況下沒有影子?
我得到了IllegalAccess,所以我複製了這個類,如果我需要這個在一個小應用程序。
我知道這並不好,但ShadowEffect不能用於其他任何類。 :(
例子:
public class Example extends JFrame {
private JSlider slider = new JSlider(JSlider.VERTICAL,0,20,2);
private JTextField txt = new JTextField();
private BufferedImage raw = null;
private Image src = null;
private Rectangle rect = new Rectangle(400,200);
public Example() {
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
repaint();
}
});
JButton btn = new JButton(new AbstractAction("load") {
@Override
public void actionPerformed(ActionEvent ev) {
try {
src = new ImageIcon(new URL(txt.getText())).getImage();
rect = new Rectangle(src.getWidth(null), src.getHeight(null));
raw = new BufferedImage(rect.width+20, rect.height+20, BufferedImage.TYPE_INT_ARGB);
raw.getGraphics().drawImage(src, 0, 0, null);
pack();
} catch(Exception e) {
e.printStackTrace();
}
}
});
JPanel ori = new JPanel(new BorderLayout());
ori.add(txt, BorderLayout.CENTER);
txt.setText("http://upload.wikimedia.org/wikipedia/en/d/d5/Transparent_google_logo.png");
ori.add(btn, BorderLayout.EAST);
JPanel pnl = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
if(raw != null && src != null){
BufferedImage dst = new BufferedImage(rect.width+20, rect.height+20, BufferedImage.TYPE_INT_ARGB);
new MyEffect().applyEffect(raw, dst, rect.width+20, rect.height+20);
g.drawImage(dst, slider.getValue(), slider.getValue(), null);
g.drawImage(src, 0, 0, null);
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(rect.width+5,rect.height+5);
}
};
setDefaultCloseOperation(EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout());
getContentPane().setBackground(Color.WHITE);
getContentPane().add(ori, BorderLayout.NORTH);
getContentPane().add(pnl, BorderLayout.CENTER);
getContentPane().add(slider, BorderLayout.EAST);
pack();
}
public static void main(String[] args) {
try {
for(UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch(Exception system) {
system.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Example().setVisible(true);
}
});
}
enum EffectType {
UNDER, BLENDED, OVER
}
public class MyEffect {
protected Color color = Color.BLACK;
/** Opacity a float 0-1 for percentage */
protected float opacity = 0.75f;
/** Angle in degrees between 0-360 */
protected int angle = 135;
/** Distance in pixels */
protected int distance = 5;
/** The shadow spread between 0-100 % */
protected int spread = 0;
/** Size in pixels */
protected int size = 5;
protected ArrayCache getArrayCache() {
ArrayCache cache = (ArrayCache)AppContext.getAppContext().get(ArrayCache.class);
if(cache == null) {
cache = new ArrayCache();
AppContext.getAppContext().put(ArrayCache.class, cache);
}
return cache;
}
protected class ArrayCache {
private SoftReference<int[]> tmpIntArray = null;
private SoftReference<byte[]> tmpByteArray1 = null;
private SoftReference<byte[]> tmpByteArray2 = null;
private SoftReference<byte[]> tmpByteArray3 = null;
protected int[] getTmpIntArray(int size) {
int[] tmp;
if(tmpIntArray == null || (tmp = tmpIntArray.get()) == null || tmp.length < size) {
// create new array
tmp = new int[size];
tmpIntArray = new SoftReference<int[]>(tmp);
}
return tmp;
}
protected byte[] getTmpByteArray1(int size) {
byte[] tmp;
if(tmpByteArray1 == null || (tmp = tmpByteArray1.get()) == null || tmp.length < size) {
// create new array
tmp = new byte[size];
tmpByteArray1 = new SoftReference<byte[]>(tmp);
}
return tmp;
}
protected byte[] getTmpByteArray2(int size) {
byte[] tmp;
if(tmpByteArray2 == null || (tmp = tmpByteArray2.get()) == null || tmp.length < size) {
// create new array
tmp = new byte[size];
tmpByteArray2 = new SoftReference<byte[]>(tmp);
}
return tmp;
}
protected byte[] getTmpByteArray3(int size) {
byte[] tmp;
if(tmpByteArray3 == null || (tmp = tmpByteArray3.get()) == null || tmp.length < size) {
// create new array
tmp = new byte[size];
tmpByteArray3 = new SoftReference<byte[]>(tmp);
}
return tmp;
}
}
Color getColor() {
return color;
}
void setColor(Color color) {
Color old = getColor();
this.color = color;
}
float getOpacity() {
return opacity;
}
void setOpacity(float opacity) {
float old = getOpacity();
this.opacity = opacity;
}
int getAngle() {
return angle;
}
void setAngle(int angle) {
int old = getAngle();
this.angle = angle;
}
int getDistance() {
return distance;
}
void setDistance(int distance) {
int old = getDistance();
this.distance = distance;
}
int getSpread() {
return spread;
}
void setSpread(int spread) {
int old = getSpread();
this.spread = spread;
}
int getSize() {
return size;
}
void setSize(int size) {
int old = getSize();
this.size = size;
}
EffectType getEffectType() {
return EffectType.UNDER;
}
BufferedImage applyEffect(BufferedImage src, BufferedImage dst, int w, int h) {
if(src == null || src.getType() != BufferedImage.TYPE_INT_ARGB) {
throw new IllegalArgumentException("Effect only works with "
+ "source images of type BufferedImage.TYPE_INT_ARGB.");
}
if(dst != null && dst.getType() != BufferedImage.TYPE_INT_ARGB) {
throw new IllegalArgumentException("Effect only works with "
+ "destination images of type BufferedImage.TYPE_INT_ARGB.");
}
// calculate offset
double trangleAngle = Math.toRadians(angle - 90);
int offsetX = (int)(Math.sin(trangleAngle) * distance);
int offsetY = (int)(Math.cos(trangleAngle) * distance);
// clac expanded size
int tmpOffX = offsetX + size;
int tmpOffY = offsetX + size;
int tmpW = w + offsetX + size + size;
int tmpH = h + offsetX + size;
// create tmp buffers
int[] lineBuf = getArrayCache().getTmpIntArray(w);
byte[] tmpBuf1 = getArrayCache().getTmpByteArray1(tmpW * tmpH);
Arrays.fill(tmpBuf1, (byte)0x00);
byte[] tmpBuf2 = getArrayCache().getTmpByteArray2(tmpW * tmpH);
// extract src image alpha channel and inverse and offset
Raster srcRaster = src.getRaster();
for(int y = 0; y < h; y++) {
int dy = (y + tmpOffY);
int offset = dy * tmpW;
srcRaster.getDataElements(0, y, w, 1, lineBuf);
for(int x = 0; x < w; x++) {
int dx = x + tmpOffX;
tmpBuf1[offset + dx] = (byte)((lineBuf[x] & 0xFF000000) >>> 24);
}
}
// blur
float[] kernel = createGaussianKernel(size);
blur(tmpBuf1, tmpBuf2, tmpW, tmpH, kernel, size); // horizontal pass
blur(tmpBuf2, tmpBuf1, tmpH, tmpW, kernel, size);// vertical pass
//rescale
float spread = Math.min(1/(1 - (0.01f * this.spread)), 255);
for(int i = 0; i < tmpBuf1.length; i++) {
int val = (int)((tmpBuf1[i] & 0xFF) * spread);
tmpBuf1[i] = (val > 255) ? (byte)0xFF : (byte)val;
}
// create color image with shadow color and greyscale image as alpha
if(dst == null) {
dst = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
}
WritableRaster shadowRaster = dst.getRaster();
int red = color.getRed(), green = color.getGreen(), blue = color.getBlue();
for(int y = 0; y < h; y++) {
int srcY = y + tmpOffY;
int shadowOffset = (srcY - offsetY) * tmpW;
for(int x = 0; x < w; x++) {
int srcX = x + tmpOffX;
lineBuf[x] = tmpBuf1[shadowOffset + (srcX - offsetX)] << 24 | red << 16 | green << 8 | blue;
}
shadowRaster.setDataElements(0, y, w, 1, lineBuf);
}
return dst;
}
}
static float[] createGaussianKernel(int radius) {
if(radius < 1) {
throw new IllegalArgumentException("Radius must be >= 1");
}
float[] data = new float[radius * 2 + 1];
float sigma = radius/3.0f;
float twoSigmaSquare = 2.0f * sigma * sigma;
float sigmaRoot = (float)Math.sqrt(twoSigmaSquare * Math.PI);
float total = 0.0f;
for(int i = -radius; i <= radius; i++) {
float distance = i * i;
int index = i + radius;
data[index] = (float)Math.exp(-distance/twoSigmaSquare)/sigmaRoot;
total += data[index];
}
for(int i = 0; i < data.length; i++) {
data[i] /= total;
}
return data;
}
static void blur(byte[] srcPixels, byte[] dstPixels, int width, int height, float[] kernel, int radius) {
float p;
int cp;
for(int y = 0; y < height; y++) {
int index = y;
int offset = y * width;
for(int x = 0; x < width; x++) {
p = 0.0f;
for(int i = -radius; i <= radius; i++) {
int subOffset = x + i;
// if (subOffset < 0) subOffset = 0;
// if (subOffset >= width) subOffset = width-1;
if(subOffset < 0 || subOffset >= width) {
subOffset = (x + width) % width;
}
int pixel = srcPixels[offset + subOffset] & 0xFF;
float blurFactor = kernel[radius + i];
p += blurFactor * pixel;
}
cp = (int)(p + 0.5f);
dstPixels[index] = (byte)(cp > 255 ? 255 : cp);
index += height;
}
}
}
}
發生了什麼事,當你試圖;-) – kleopatra
'java.lang.IllegalAccessError:試圖訪問類com.sun.java.swing.plaf.nimbus.DropShadowEffect' – oliholz
好完成,oliholz :-)。向前一小步。 – AgostinoX