谁能解释为什么 Nimbius 对待 setOpaque() 的方式与其他 java LaF 不同。它破坏了我的代码,因为通常透明的组件不再是。
编辑:这个问题似乎只涉及 JTextAreas (这是我需要的)或类似的组件。
编辑编辑:这是实际应用程序的屏幕。在应用垃圾神解决方案时,背景仍然没有显示出来。
编辑 编辑 编辑:
我尝试了垃圾上帝的建议来覆盖paint()。我为此辛勤工作了几个小时,但无法让它工作。我能够让背景显示出来,但是 JinternalFrame 无法移动、调整大小和选择其文本。调用 super.paint(g) 未能解决解决方案。有没有一种我可能会错过的简单方法来做到这一点?
我对此采取了新的方法。JInternalFrame 内部是一个 JLayeredPane。
第 0 层 - JLabel
第 1 层 - JTextArea
当 JInternalFrame 移动或调整大小时:
- 让自己隐形
- 截取它在容器中所在位置的屏幕截图
- 用它拍摄的图像绘制 JLabel
- 使自己再次可见。
因为我根本无法让 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);
}
}