Полупрозрачные компоненты внутри JPanel

У меня есть класс MyPanel, который наследуется от JPanel. Класс MyPanel имеет компонент JLabel, который содержит значок.

Мой вопрос заключается в том, как я могу нарисовать/рендерить этот компонент JLabel, чтобы получить полупрозрачный эффект (видимый сквозь значок) внутри класса MyPanel (не создавать xxxJLabel, расширяющий класс JLabel и переопределяющий метод paintComponents).

Спасибо


person MinhHoang    schedule 20.08.2011    source источник
comment
нет, я пытаюсь переопределить метод painComponent (Graphics g) класса MyPanel, но безуспешно   -  person MinhHoang    schedule 20.08.2011
comment
Ответ ниже: Эндрю Томпсон должен покрыть это. Убедитесь, что вы проголосовали за него, так как он приложил значительные усилия.   -  person Romain Hippeau    schedule 20.08.2011


Ответы (1)


Один из способов — предоставить полупрозрачное изображение для JLabel. Это можно сделать с помощью стандартной метки перед вызовом setIcon() или аналогичного метода или альтернативно, расширив JLabel и переопределив метод setIcon(), чтобы сделать то же самое.

НАПРИМЕР. 2-й техники

введите здесь описание изображения

Код

import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.net.URL;

class TransparentIcon {
    public static void main(String[] args) throws Exception {
        String imgURL =
            "http://www.gravatar.com/avatar/" +
            "a1ab0af4997654345d7a949877f8037e";
        final BufferedImage image = ImageIO.read(new URL(imgURL));
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                ImageIcon icon = new ImageIcon(image);

                JPanel  p = new JPanel(new GridLayout(2,3));
                for (int ii=0; ii<6; ii++) {
                    TransparentLabel tl = new TransparentLabel();
                    tl.setOpacity((ii+1)/6f);
                    tl.setIcon(icon);
                    p.add(tl);
                }

                JOptionPane.showMessageDialog(null, p);
            }
        });
    }
}

class TransparentLabel extends JLabel {

    float opacity = 1f;

    public void setOpacity(float opacity) {
        this.opacity = opacity;
    }

    private Icon getTranslucentIcon(Icon icon) {

        if (icon!=null) {
            BufferedImage bi = new BufferedImage(
                icon.getIconWidth(),
                icon.getIconHeight(),
                BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = bi.createGraphics();
            AlphaComposite ac = AlphaComposite.getInstance(
                AlphaComposite.SRC_OVER,
                opacity);
            g.setComposite(ac);
            icon.paintIcon(this,g,0,0);
            g.dispose();

            return new ImageIcon(bi);
        } else {
            return null;
        }
    }

    public void setIcon(Icon icon) {
        super.setIcon( getTranslucentIcon(icon) );
    }
}

Обновлять

Мне просто интересно, как это можно сделать, если я получу графику JLabel внутри класса MyPanel и изменю ее внешний вид?

LabelRenderTest.java отображает JLabel в BufferedImage, чтобы он может использоваться для пользовательского рендеринга внутри метода paintComponent(Graphics).

Обратите внимание: я не совсем понимаю, в чем преимущество JLabel в вашем случае использования. Я использовал его в этом примере для отображения HTML. Если бы у меня было только изображение, я бы использовал его напрямую (например, Graphics.drawImage(Image,int,int,ImageObserver)) и никогда не создавал ярлык.

person Andrew Thompson    schedule 20.08.2011
comment
Привет, ты неправильно понял мою мысль! Изнутри класса MyPanel я хочу сделать компонент JLabel полупрозрачным, вызвав метод JLabel.getGraphics(), а затем выполнив здесь полупрозрачные действия. - person MinhHoang; 20.08.2011
comment
Возможно, но ваша идея просто глупа. Никогда не звоните getGraphics() (если вы действительно не знаете, что делаете). Кроме того, вы путаете стратегию с целью. Я до сих пор не понимаю цели, потому что ты еще не ясно ее сформулировал. Вы продолжаете сосредотачиваться на том, как вы хотите достичь цели (то есть на ошибочной стратегии). - person Andrew Thompson; 20.08.2011
comment
@Final: я полностью согласен с Эндрю - вы не хотите использовать объект Graphics компонента, полученного с помощью getGraphics. Во-первых, он не будет сохраняться при перерисовке. На вашем месте я бы согласился с предложениями Эндрю (1+). - person Hovercraft Full Of Eels; 20.08.2011
comment
Спасибо! Мне просто интересно, как это можно сделать, если я получу графику JLabel внутри класса MyPanel и изменю ее внешний вид? - person MinhHoang; 20.08.2011
comment
Спасибо Андрей очень помогло - person MinhHoang; 21.08.2011
comment
хммм... не совсем понимаю ни проблему, ни предлагаемые решения: все, что нужно, это прозрачный значок, верно? Не вижу необходимости создавать подклассы для какого-либо компонента — достаточно утилиты, содержащей код прозрачности значков, anyLabel.setIcon(transparentize(myIcon)). Вероятность того, что я что-то упустил, не равна нулю, поскольку решение исходит от @Andrew :-) Что мне не хватает? - person kleopatra; 21.08.2011
comment
@kleopatra Эй, я тоже не могу сказать, что понимаю этот вопрос. Я просто сделал несколько «ударов в темноте», потому что мне было скучно, и была возможность сделать снимки экрана. ;) - person Andrew Thompson; 21.08.2011
comment
хач... хромое оправдание ненужного подкласса :-) - person kleopatra; 21.08.2011