作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在我的 Swing 应用程序中使用了 Nimbus 外观,它非常酷。
我注意到它是一种“纯粹”的外观和感觉:它“蒙皮”组件,但不添加新的图形元素。
我想知道它的渲染技术的某些部分是否可以重用,例如类:
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;
}
}
}
}
关于java - Swing 灵气 ShadowEffect,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7254586/
我在我的 Swing 应用程序中使用了 Nimbus 外观,它非常酷。 我注意到它是一种“纯粹”的外观和感觉:它“蒙皮”组件,但不添加新的图形元素。 我想知道它的渲染技术的某些部分是否可以重用,例如类
在 Firemonkey 中,我们可以使用 TShadowEffect 来绘制漂亮的阴影。 此阴影还会调整其不透明度和半透明度,以便在控件重叠时在其下方显示正确的组件。 没有 TShadowEffec
我是一名优秀的程序员,十分优秀!