1

を介して背景として画像が描画された JPanel がありpaintComponent()、このパネルにはアイコン付きのボタンがいくつか含まれているとします。ボタンには独自の背景がなく、パネルの背景を「継承」します。でボタンのアイコンを半透明にする方法は知っていますAlphaCompositeが、ボタンの背景画像 (ボタンは不透明でパネルの背景にペイントされているため、JPanel の背景画像の一部です) を取得して透明にする方法はありますか?アイコン?これが可能かどうかさえわかりません...

次のコードは、ボタンのアイコンを透明にするだけです。

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.image.BufferedImage;

import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TestPanel extends JPanel {

    private final ImageIcon icon = new ImageIcon(getClass().getResource("path\\to\\image\\file"));
    private BufferedImage img;

    public TestPanel() {

        try {
            img = ImageIO.read(new File("path\\to\\background\\image"));
        } catch (IOException ex) {}

        ImageIcon fadedIcon = getTranslucentImageIcon(icon, 0.5f);
        JButton button = new JButton(fadedIcon);
        button.setRolloverIcon(icon);
        button.setBorder(BorderFactory.createLineBorder(Color.BLACK));
        button.setOpaque(false);
        button.setContentAreaFilled(false);
        button.setFocusPainted(false);
        this.add(button);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(img, 0, 0, null);
    }

    @Override
    public Dimension getPreferredSize() {
        if (img != null) {
          return new Dimension(img.getWidth(), img.getHeight());
        }
        return super.getPreferredSize();
    }

    private BufferedImage getTranslucentImage(BufferedImage oldImg, float alpha) {
        int w = oldImg.getWidth();
        int h = oldImg.getHeight();
        BufferedImage newImg = new BufferedImage(w, h, BufferedImage.TRANSLUCENT);
        Graphics2D g2d = newImg.createGraphics();
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
        g2d.drawImage(oldImg, null, 0, 0);
        g2d.dispose();
        return newImg;
    }

    private ImageIcon getTranslucentImageIcon(Icon oldIcon, float alpha) {
        int w = oldIcon.getIconWidth();
        int h = oldIcon.getIconHeight();
        BufferedImage oldImg = new BufferedImage(w, h, BufferedImage.TRANSLUCENT);
        Graphics2D g2d = (Graphics2D) oldImg.getGraphics();
        oldIcon.paintIcon(null, g2d, 0, 0);
        BufferedImage newImg = getTranslucentImage(oldImg, alpha);
        g2d.dispose();
        return new ImageIcon(newImg);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPanel());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }

}

再現するには2つの画像が必要です(私の主張を明確にするために、背景画像は大きくする必要があります)。

PSまた、私がすべてを正しく行っているかどうか(より具体的な方法getTranslucentImageと方法getTranslucentImageIcon)、またはそれを行うためのより良い方法があるかどうかも知りたいです。

4

1 に答える 1

3

コメントはフォーマットに適していないため、ここに配置します。

あなたの「半透明の」方法に関しては、それらは私には問題ないようです。私が行う可能性のある唯一の変更は、代わりに互換性のあるバッファリングされたイメージを作成することです。これにより、(とりわけ)カラーモデルが同じになり、レンダリングが高速になります...

protected BufferedImage createCompatibleImage(int width, int height, int transparency) {
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice gs = ge.getDefaultScreenDevice();
    GraphicsConfiguration gc = gs.getDefaultConfiguration();
    return gc.createCompatibleImage(width, height, transparency);
}

private BufferedImage getTranslucentImage(BufferedImage oldImg, float alpha) {
    int w = oldImg.getWidth();
    int h = oldImg.getHeight();
    BufferedImage newImg = createCompatibleImage(w, h, Transparency.TRANSLUCENT);
    Graphics2D g2d = newImg.createGraphics();
    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
    g2d.drawImage(oldImg, null, 0, 0);
    g2d.dispose();
    return newImg;
}

拡張回答で更新

私はあなたが望むものを達成するために、あなたは親コンポーネントのクリーンなバージョンを必要とするでしょう。それは子供がいないコピーです。次に、サイズを変更し、このコピーをオフスクリーンバッファ(バッファリングされた画像など)にペイントしてから、必要な画像の部分を抽出します(または要件に基づいてサブ画像をペイントします)。

率直に言って。あなたがしていることは単に簡単です...

于 2012-09-25T22:56:23.100 に答える