java中的setOpaque()

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

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

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

替代文字

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

移动或调整JInternalFrame时:

  1. 使自己看不见
  2. 拍摄它所包含的容器中的位置的屏幕截图
  3. 用它拍摄的图像绘制JLabel
  4. 使自己再次可见。

因为我无法让JInternalFrame完全透明。 我模拟了它的透明度。 唯一的问题是,与此相关的开销很大。 有什么想法吗?

替代文字

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); } } 

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

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

关于您的代码的一些注意事项:

  • 始终在事件派发线程上构建GUI。
  • 不要从另一个线程中绘制。
  • 不要吞下exception。

附录:查看对create()更改。

附录:您可能也想查看isPalette属性

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

替代文字

 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(); } }); } } 

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