如何使 JFrame contentPane 透明但 JFrame 可见?
How to make the JFrame contentPane transparent but the JFrame visible?
我想知道如何使 JFrame 的 contentPane 透明但 JFrame 可见。我看了很多页面,但都显示了如何使 JFrame 边框可见但 contentPane 可见。
我尝试使用 setOpacity()
,但这要求 JFrame 为 undecorated
。
有什么方法可以实现吗?
您可以对 JFrame
中的每个元素使用 setVisible(false)
方法。您在 intialize()
方法中使用它。一旦您希望显示它们(例如在单击某个按钮后),您将使用相同的方法 setVisible(true)
.
Swing 未设计为使用透明背景进行绘制。您不能创建透明的 contentPane。但是,您可以伪造一个透明背景。
这是显示假透明背景的屏幕截图。我将图像裁剪并缩小了 50% 以使其显示在此答案中。
那么,我是怎么做到的?
我拍了一张背景快照,然后在 JPanel
上画了背景。
仅当您在显示 JFrame
时 不更改背景 时才有效。如果您通过打开或关闭任何其他应用程序来更改背景,这个假 将不起作用。
您可以移动 JFrame
。不要将 JFrame 移动到靠近屏幕边缘,否则会破坏幻觉。
图标化和非图标化 JFrame
有效,但错觉变得明显。
您可以调整大小、最大化和还原 JFrame
。
需要大量代码才能使这个伪造正常工作。
这是完整的可运行代码。我将所有额外的 类 都放在 类 内部,这样我就可以 post 将这段代码作为一个块。
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);
}
}
}
我想知道如何使 JFrame 的 contentPane 透明但 JFrame 可见。我看了很多页面,但都显示了如何使 JFrame 边框可见但 contentPane 可见。
我尝试使用 setOpacity()
,但这要求 JFrame 为 undecorated
。
有什么方法可以实现吗?
您可以对 JFrame
中的每个元素使用 setVisible(false)
方法。您在 intialize()
方法中使用它。一旦您希望显示它们(例如在单击某个按钮后),您将使用相同的方法 setVisible(true)
.
Swing 未设计为使用透明背景进行绘制。您不能创建透明的 contentPane。但是,您可以伪造一个透明背景。
这是显示假透明背景的屏幕截图。我将图像裁剪并缩小了 50% 以使其显示在此答案中。
那么,我是怎么做到的?
我拍了一张背景快照,然后在 JPanel
上画了背景。
仅当您在显示 JFrame
时 不更改背景 时才有效。如果您通过打开或关闭任何其他应用程序来更改背景,这个假 将不起作用。
您可以移动 JFrame
。不要将 JFrame 移动到靠近屏幕边缘,否则会破坏幻觉。
图标化和非图标化 JFrame
有效,但错觉变得明显。
您可以调整大小、最大化和还原 JFrame
。
需要大量代码才能使这个伪造正常工作。
这是完整的可运行代码。我将所有额外的 类 都放在 类 内部,这样我就可以 post 将这段代码作为一个块。
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);
}
}
}