setOpaque () в Java - PullRequest
       48

setOpaque () в Java

4 голосов
/ 03 ноября 2010

Может кто-нибудь объяснить, почему Нимбиус рассматривает setOpaque () иначе, чем другие Java-LaF.Это нарушает мой код, потому что компоненты, которые обычно прозрачны, больше не являются.

РЕДАКТИРОВАТЬ: Проблема, кажется, касается только JTextAreas (что мне нужно) или подобных компонентов.

РЕДАКТИРОВАТЬ РЕДАКТИРОВАТЬ:Это экран самого приложения.При применении решения trashgod фон по-прежнему не просвечивает.

alt text

РЕДАКТИРОВАТЬ РЕДАКТИРОВАТЬ РЕДАКТИРОВАТЬ:
Я попробовал предложение trashgod переопределить краску ().Я трудился с этим часами и не мог заставить его работать.Мне удалось просвечивать фон, но JinternalFrame не удалось переместить, изменить размер и выделить его текст.Вызов super.paint (g) не смог решить проблему.Есть ли простой способ сделать это, что я могу пропустить?
Я выбрал новый подход к этому.Внутри JInternalFrame находится JLayeredPane.
Слой 0 - JLabel
Слой 1 - JTextArea

Когда JInternalFrame перемещается или изменяется:

  1. Делает себя невидимым
  2. Делает снимок экрана с тем, где он был в контейнере, в котором он содержится в
  3. Окрашивает JLabel изображением, которое он взял
  4. Делает себя видимым снова.

Так как я не мог сделать JInternalFrame прозрачным вообще.Я смоделировал его прозрачность.Единственная проблема заключается в том, что с этим связано много накладных расходов.Есть мысли?

alt text


package newpackage;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.UIManager;

/**
 * Example of how to create a transparent internal frame.
 * @author dvargo
 */
public class TransparentInternalFrame extends JInternalFrame {

    JLayeredPane container;


    /**
     * Defualt constructor to set the frame up
     * @param container The container for the frame
     * @param opacity The opacity of the frame
     */
    public TransparentInternalFrame(JLayeredPane container, int opacity) {
        super("", true, true, true, true);
        this.container = container;
        initComponents();
        setSize(200, 200);
        putClientProperty("JInternalFrame.isPalette", Boolean.TRUE);
        scrollPane.setBackground(new Color(0, 0, 0, opacity));
        scrollPane.getViewport().setBackground(new Color(0, 0, 0, opacity));
        textArea.setBackground(new Color(0, 0, 0, opacity));
        setBG();
    }

    /**
     * Builds the GUI
     */
    private void initComponents() {

        layeredPane = new javax.swing.JLayeredPane();
        imageLabel = new javax.swing.JLabel();
        scrollPane = new javax.swing.JScrollPane();
        textArea = new javax.swing.JTextArea();

        imageLabel.setBounds(0, 0, 360, 260);
        layeredPane.add(imageLabel, javax.swing.JLayeredPane.DEFAULT_LAYER);

        scrollPane.setBorder(null);

        textArea.setColumns(20);
        textArea.setRows(5);
        textArea.addKeyListener(new java.awt.event.KeyAdapter() {

            public void keyPressed(java.awt.event.KeyEvent evt) {
                textAreaKeyPressed(evt);
            }

            public void keyReleased(java.awt.event.KeyEvent evt) {
                textAreaKeyReleased(evt);
            }

            public void keyTyped(java.awt.event.KeyEvent evt) {
                textAreaKeyTyped(evt);
            }
        });

        addComponentListener(new java.awt.event.ComponentAdapter() {

            public void componentMoved(java.awt.event.ComponentEvent evt) {
                frameMoved();
            }

            public void componentResized(java.awt.event.ComponentEvent evt) {
                frameResized();
            }
        });

        scrollPane.setViewportView(textArea);

        scrollPane.setBounds(0, 0, 360, 260);
        layeredPane.add(scrollPane, javax.swing.JLayeredPane.PALETTE_LAYER);



        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
       getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(layeredPane, javax.swing.GroupLayout.PREFERRED_SIZE, 362, javax.swing.GroupLayout.PREFERRED_SIZE));
        layout.setVerticalGroup(
              layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(layeredPane, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE));
    }

    /**
     * The text will be blurred with out this
     * @param evt
     */
    private void textAreaKeyTyped(java.awt.event.KeyEvent evt) {
        repaintAll();
    }

    /**
     * The text will be blurred with out this
     * @param evt
     */
    private void textAreaKeyPressed(java.awt.event.KeyEvent evt) {
        repaintAll();
    }

    /**
     * The text will be blurred with out this
     * @param evt
     */
    private void textAreaKeyReleased(java.awt.event.KeyEvent evt) {
        repaintAll();
    }

    /**
     * Capture whats behind the frame and paint it to the image label
     */
    private void setBG() {

        setVisible(false);
        Rectangle location = new Rectangle(this.getX() + container.getX(),
                this.getY() + container.getY(),
                (int) this.getSize().getWidth() + 8 + ((javax.swing.plaf.basic.BasicInternalFrameUI) getUI()).getNorthPane().getWidth(),
                (int) this.getSize().getHeight() + ((javax.swing.plaf.basic.BasicInternalFrameUI) getUI()).getNorthPane().getHeight() + 4);
        ImageIcon newIcon = new ImageIcon(createImage((JComponent) container, location));
        setVisible(true);
        imageLabel.setIcon(newIcon);
        repaint();
    }

    /**
     * Only need to update the image label if the frame is moved or resized
     */
    private void frameResized() {
        setBG();
        textArea.repaint();
    }

    /**
     * Only need to update the image label if the frame is moved or resized
     */
    private void frameMoved() {
        setBG();
        for(Component x : container.getComponents())
        {
            //see if its a jinternalframe
            if(x.getClass().getName().equals(this.getClass().getName()))
            {
                //cast it
                TransparentInternalFrame temp = (TransparentInternalFrame)x;
                //make sure its not the same one as this
                if(x.getBounds().equals(this.getBounds()))
                {
                    return;
                }
                //if they intersect
                if(x.getBounds().intersects(this.getBounds()))
                {
                    this.setVisible(false);
                    temp.setBG();
                    this.setVisible(true);
                }
            }
        }

        textArea.repaint();
    }

    private void repaintAll() {
        textArea.repaint();
        imageLabel.repaint();
        layeredPane.repaint();
        scrollPane.repaint();
        scrollPane.getViewport().repaint();
        textArea.repaint();
        repaint();
    }

    /**
     *  Create a BufferedImage for Swing components.
     *  All or part of the component can be captured to an image.
     *
     *  @param  component Swing component to create image from
     *  @param  region The region of the component to be captured to an image
     *  @return image the image for the given region
     */
    public static BufferedImage createImage(JComponent component, Rectangle region) {
        //  Make sure the component has a size and has been layed out.
        //  (necessary check for components not added to a realized frame)

        if (!component.isDisplayable()) {
            Dimension d = component.getSize();

            if (d.width == 0 || d.height == 0) {
                d = component.getPreferredSize();
                component.setSize(d);
            }

            layoutComponent(component);
        }

        BufferedImage image = new BufferedImage(region.width, region.height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = image.createGraphics();

        //  Paint a background for non-opaque components,
        //  otherwise the background will be black

        if (!component.isOpaque()) {
            g2d.setColor(component.getBackground());
            g2d.fillRect(region.x, region.y, region.width, region.height);
        }

        g2d.translate(-region.x, -region.y);
        component.paint(g2d);
        g2d.dispose();
        return image;
    }

    public static void layoutComponent(Component component) {
        synchronized (component.getTreeLock()) {
            component.doLayout();

            if (component instanceof Container) {
                for (Component child : ((Container) component).getComponents()) {
                    layoutComponent(child);
                }
            }
        }
    }
    private javax.swing.JLabel imageLabel;
    private javax.swing.JScrollPane scrollPane;
    private javax.swing.JLayeredPane layeredPane;
    private javax.swing.JTextArea textArea;


    public static void main(String args[])
    {
        try
        {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        JFrame container = new JFrame();
        container.setSize(800, 800);

        JLayeredPane layerPanel = new JLayeredPane();
        layerPanel.setSize(800, 800);
        container.getContentPane().add(layerPanel);
        layerPanel.setVisible(true);

        JPanel colorPanel = new JPanel();
        colorPanel.setSize(800,800);
        colorPanel.setBackground(Color.red);
        layerPanel.add(colorPanel);
        layerPanel.setLayer(colorPanel, JLayeredPane.DEFAULT_LAYER);

        TransparentInternalFrame frameA = new TransparentInternalFrame(layerPanel,0);
        frameA.setVisible(true);
        layerPanel.add(frameA);
        layerPanel.setLayer(frameA, 1);
        frameA.setSize(282,282);

        TransparentInternalFrame frameB = new TransparentInternalFrame(layerPanel, 0);
        frameB.setVisible(true);
        layerPanel.add(frameB);
        layerPanel.add(frameB,1);
        frameB.setLocation(300, 300);
        frameB.setSize(282,282);

        container.repaint();
        container.setVisible(true);

    }
}


Ответы [ 2 ]

11 голосов
/ 03 ноября 2010

Вы можете получить некоторые сведения из раздела Непрозрачность в статье Рисование в AWT и Swing .В частности, установка непрозрачного свойства не означает «Сделать фон компонента прозрачным». sscce , который демонстрирует проблему, также может быть плодотворным.

Приложение: Упрощая ваш пример, похоже, что сама текстовая область может быть сделана прозрачной, но Nimbus по умолчанию влияют на границы области.Вы можете попытаться изменить их соответствующим образом.

Несколько замечаний по вашему коду:

  • Всегда создавайте свой графический интерфейс в потоке отправки событий.
  • Не извлекайте издругой поток.
  • Не глотайте исключение.

Добавление: см. изменения в create().

Приложение: Возможно, вы захотите взглянуть на isPalette свойство тоже

jif.putClientProperty("JInternalFrame.isPalette", Boolean.TRUE);

alt text

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import javax.swing.JInternalFrame;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.UIManager;

public class TransparentTextArea extends JTextArea {

    int alpha;

    public TransparentTextArea(int alpha) {
        super(4, 16);
        this.alpha = alpha;
        this.setBackground(new Color(0, 0, 0, alpha));
        this.setFont(new Font("Serif", Font.ITALIC, 24));
        this.setEditable(false);
        this.setText("Twas brillig and the slithy toves,\n"
            + "Did gyre and gimble in the wabe;\n"
            + "All mimsy were the borogoves,\n"
            + "And the mome raths outgrabe.");
    }

    private static void create() {
        JFrame f = new JFrame();
        f.setLayout(new FlowLayout());
        f.getContentPane().setBackground(new Color(0xffffc0));
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JInternalFrame jif = new JInternalFrame();
        JPanel panel = new JPanel();
        panel.setBackground(new Color(0xffffc0));
        panel.add(new TransparentTextArea(0));
        jif.add(panel);
        jif.setVisible(true);

        f.add(jif);
        f.pack();
        f.setVisible(true);
    }

    public static void main(String[] args) {

        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
        } catch (Exception e) {
            e.printStackTrace();
        }

        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                create();
            }
        });
    }
}
1 голос
/ 08 ноября 2010

Как объяснено здесь , setOpaque не делает то, что вы думаете, что он делает, и эта ошибка становится очевидной в Nimbus. Другой ответ, который относится к альфа-цвету, является правильным способом достижения того, что вы хотите.

...