java中的setOpaque()

时间:2010-11-03 17:19:12

标签: java swing look-and-feel nimbus

任何人都可以解释为什么Nimbius以不同于其他java LaF的方式处理setOpaque()。它破坏了我的代码,因为通常透明的组件不再是。

编辑:问题似乎只涉及JTextAreas(这是我需要的)或类似的组件。

编辑编辑:这是实际应用程序的屏幕。在应用trashgod的解决方案时,背景仍然无法显示。

alt text

编辑编辑编辑:
我尝试了trashgod的建议来覆盖油漆()。我辛苦工作了好几个小时,无法让它发挥作用。我能够显示背景,但JinternalFrame无法移动,调整大小并选择其文本。调用super.paint(g)无法解决问题。有没有一种简单的方法可以让我失踪?
我采取了一种新方法。 JInternalFrame内部是一个JLayeredPane 第0层 - JLabel
第1层 - JTextArea

移动或调整JInternalFrame的大小时:

  1. 使自己隐身
  2. 在屏幕截图中显示
  3. 中包含的容器的位置
  4. 使用拍摄的图像绘制JLabel
  5. 让自己再次可见。
  6. 因为我无法让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 个答案:

答案 0 :(得分:11)

您可以从文章Opacity中的Painting in AWT and Swing部分获得一些见解。特别是,设置opaque属性并不意味着“使组件的背景透明”。证明问题的sscce也可能富有成效。

附录:简化您的示例,看起来文本区域本身可以变得透明,但Nimbus defaults正在影响区域的边界。您可以尝试相应地更改它们。

关于您的代码的一些注释:

  • 始终在事件派发线程上构建GUI。
  • 不要从另一个线程中抽取。
  • 不要吞下异常。

附录:查看对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 :(得分:1)

正如here所解释的那样,setOpaque并没有像你想象的那样做,并且在Nimbus中失败是显而易见的。另一个涉及alpha颜色的答案是完成你想要的正确方法。