任何人都可以解释为什么Nimbius以不同于其他java LaF的方式处理setOpaque()。它破坏了我的代码,因为通常透明的组件不再是。
编辑:问题似乎只涉及JTextAreas(这是我需要的)或类似的组件。
编辑编辑:这是实际应用程序的屏幕。在应用trashgod的解决方案时,背景仍然无法显示。
编辑编辑编辑:
我尝试了trashgod的建议来覆盖油漆()。我辛苦工作了好几个小时,无法让它发挥作用。我能够显示背景,但JinternalFrame无法移动,调整大小并选择其文本。调用super.paint(g)无法解决问题。有没有一种简单的方法可以让我失踪?
我采取了一种新方法。 JInternalFrame内部是一个JLayeredPane
第0层 - JLabel
第1层 - JTextArea
移动或调整JInternalFrame的大小时:
因为我无法让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);
}
}
答案 0 :(得分:11)
您可以从文章Opacity中的Painting in AWT and Swing部分获得一些见解。特别是,设置opaque属性并不意味着“使组件的背景透明”。证明问题的sscce也可能富有成效。
附录:简化您的示例,看起来文本区域本身可以变得透明,但Nimbus defaults正在影响区域的边界。您可以尝试相应地更改它们。
关于您的代码的一些注释:
附录:查看对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();
}
});
}
}
答案 1 :(得分:1)
正如here所解释的那样,setOpaque并没有像你想象的那样做,并且在Nimbus中失败是显而易见的。另一个涉及alpha颜色的答案是完成你想要的正确方法。