1

我想知道如何使 JFrame 的 contentPane 透明但 JFrame 可见。我看到了很多页面,但都展示了如何使 JFrame 边框可见但 contentPane 可见。

我尝试使用setOpacity(),但这需要 JFrame 是undecorated.

有什么方法可以实现吗?

4

2 回答 2

1

您可以setVisible(false)对其中的每个元素使用方法JFrame。您在intialize()方法中使用它。一旦您希望显示它们(例如在单击某个按钮后),您将使用相同的方法setVisible(true)

于 2021-12-05T13:57:34.727 回答
1

Swing 并非设计用于使用透明背景进行绘画。您不能创建透明的 contentPane。但是,您可以伪造透明背景。

这是一个显示假透明背景的屏幕截图。我将图像裁剪并缩小了 50% 以使其显示在此答案中。

在此处输入图像描述

那么,我是怎么做到的呢?

我拍了背景的快照,然后在JPanel.

仅当在显示JFrame. 如果您通过打开或关闭任何其他应用程序来更改背景,则此伪造将不起作用

你可以JFrame左右移动。不要将 JFrame 移动到靠近屏幕边缘的位置,否则会破坏错觉。

将作品图标化和去图标化JFrame,但幻觉变得明显。

您可以调整大小、最大化和恢复JFrame.

它需要大量代码才能使这个假货正常工作。

这是完整的可运行代码。我将所有附加类都设为内部类,因此我可以将此代码作为一个块发布。

import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TransparentJPanelView implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new TransparentJPanelView());
    }
    
    private DrawingPanel drawingPanel;
    
    private JFrame frame;
    
    private TransparentJPanelModel model;
    
    public TransparentJPanelView() {
        this.model = new TransparentJPanelModel();
        this.drawingPanel = new DrawingPanel(model);
    }

    @Override
    public void run() {
        this.frame = new JFrame("Fake Transparent JPanel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.addComponentListener(new FrameComponentListener(this, model));
        FrameListener listener = new FrameListener(this, model);
        frame.addWindowListener(listener);
        frame.addWindowFocusListener(listener);
        frame.addWindowStateListener(listener);

        frame.add(drawingPanel, BorderLayout.CENTER);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    public void repaint() {
        drawingPanel.repaint();
    }
    
    public JFrame getFrame() {
        return frame;
    }

    public class DrawingPanel extends JPanel {

        private static final long serialVersionUID = 1L;
        
        private TransparentJPanelModel model;
        
        public DrawingPanel(TransparentJPanelModel model) {
            this.model = model;
            this.setLayout(new FlowLayout());
            this.setPreferredSize(new Dimension(600, 300));
            
            JButton button = new JButton("Click me");
            this.add(button);
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            
            Point point = new Point(this.getLocation()); 
            SwingUtilities.convertPointToScreen(point, this); 
            
            Image image = model.getSubImage(point.x, point.y, getWidth(), getHeight());
            g.drawImage(image, 0, 0, this);
        }
        
    }
    
    public class FrameComponentListener extends ComponentAdapter {
        
        private final TransparentJPanelView view;
        
        private final TransparentJPanelModel model;
        
        public FrameComponentListener(TransparentJPanelView view, 
                TransparentJPanelModel model) {
            this.view = view;
            this.model = model;
        }

        @Override
        public void componentResized(ComponentEvent event) {
            view.repaint();
        }

        @Override
        public void componentMoved(ComponentEvent event) {
            view.repaint();
        }

    }
    
    public class FrameListener extends WindowAdapter { 

        private final TransparentJPanelView view;
        
        private final TransparentJPanelModel model;
        
        public FrameListener(TransparentJPanelView view, 
                TransparentJPanelModel model) {
            this.view = view;
            this.model = model;
        }
        
        @Override
        public void windowDeiconified(WindowEvent event) {
            model.setBackground();
            view.repaint();
        }
        
    }
    
    public class TransparentJPanelModel {
        
        private BufferedImage background;
        
        private final Rectangle screenRect;
        
        private final Robot robot;
        
        public TransparentJPanelModel() {
            this.robot = createRobot();
            this.screenRect = new Rectangle(
                    Toolkit.getDefaultToolkit().getScreenSize());
            setBackground();
        }
        
        private Robot createRobot() {
            Robot robot = null;
            try {
                robot = new Robot();
            } catch (AWTException e) {
                e.printStackTrace();
            }
            return robot;
        }

        public void setBackground() {
            this.background = robot.createScreenCapture(screenRect);
        }
        
        public Image getSubImage(int x, int y, int width, int height) {
            if (x < 0) {
                x = 0;
                width = Math.min(width, screenRect.width);
            }
            
            if (y < 0) {
                y = 0;
                height = Math.min(height, screenRect.height);
            }
            
            if (x + width > screenRect.width) {
                width = screenRect.width - x;
            }
            
            if (y + height > screenRect.height) {
                height = screenRect.height - y;
            }
            
            return background.getSubimage(x, y, width, height);
        }
        
    }
    
}
于 2021-12-06T08:42:08.117 回答