在jframe中的模糊背景上创建一个透明矩形
Posted
技术标签:
【中文标题】在jframe中的模糊背景上创建一个透明矩形【英文标题】:create an transparent rectangle over blurred background in jframe 【发布时间】:2014-06-06 13:57:04 【问题描述】:在模糊背景上创建透明矩形时遇到问题。我正在尝试在glasspane
上执行此任务。这是我的代码 sn-p。
void createBlur()
alpha = 1.0f;
JRootPane root = SwingUtilities.getRootPane(jf);
blurBuffer = GraphicsUtilities.createCompatibleImage(jf.getWidth(), jf.getHeight());
Graphics2D g2d = blurBuffer.createGraphics();
root.paint(g2d);
g2d.dispose();
backBuffer = blurBuffer;
blurBuffer = GraphicsUtilities.createThumbnailFast(blurBuffer, jf.getWidth() / 2);
blurBuffer = new GaussianBlurFilter(5).filter(blurBuffer, null);
其中,backBuffer 和 blurBuffer 是BufferedImage
& jf = JFrame 的对象,alpha 用于不透明度。
上面的方法很好地创建了模糊效果。
这是在面板上创建透明矩形的代码
protected void paintComponent(Graphics g)
int x = 34;
int y = 34;
int w = getWidth() - 68;
int h = getHeight() - 68;
int arc = 30;
//Graphics2D g2 = currentGraphics.createGraphics();
//g2.drawImage(currentGraphics, 0, 0, null);
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(0, 0, 0, 220));
g2.fillRoundRect(x, y, w, h, arc, arc);
g2.setStroke(new BasicStroke(1f));
g2.setColor(Color.WHITE);
g2.drawRoundRect(x, y, w, h, arc, arc);
g2.dispose();
现在我卡住的地方是如何同时绘制模糊效果和透明矩形。 我没有在这里发布完整的代码,如果有人想在这里看到代码link。
这是样本输出的所需图像。提前致谢。
【问题讨论】:
为了尽快获得更好的帮助,请发布MCVE(最小完整且可验证的示例)。并请澄清屏幕截图。这是你想要的效果还是你现在得到的?如果是“现在”,有什么问题? 顺便说一句,关于您的 Google 共享驱动器的链接。很少有人会关注它,“请求访问”的人更少。至少人们有礼貌地将共享文件标记为“公开”给任何知道链接的人。 @AndrewThompson 这是所需的输出,应该会出现这个输出。我能够创建一个透明的矩形和模糊的背景,但我不知道如何将它们合并在一起。很抱歉没有将文件共享为“公共” hmm ...这与swingx有什么关系? @kleopatra SwingX 库提供了一些基本类来使用 GaussianBlurFilter 获得模糊效果,它提供了一些额外的属性来创建有效的 GUI,例如 JXPanel 提供了一个名为 alpha 的公共属性,可用于更改容器和它的孩子,这就是我使用 SwingX 的原因 【参考方案1】:我正在尝试对您的代码进行正面和反面...
你没有打电话给super.paintComponent
...如果你不小心,这可能会导致你陷入同样严重的问题。一般的经验法则,只需调用它;)
修改Graphics
上下文的状态时要小心,例如...
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
将影响在此之后绘制的所有组件,并可能导致一些您没有预料到的有趣的图形故障...
jf.getGlassPane().setVisible(false);
glassPanel = new GlassPanel();
jf.getGlassPane().setVisible(true);
看起来毫无意义,因为使用jf.setGlassPane(glassPanel);
设置的组件仍然是调用jf.getGlassPane().setVisible(true);
时可见的组件。这也意味着永远不会使用GlassPane
组件...
在paintComponent
中检查isVisible
毫无意义,因为Swing 足够聪明,知道不要绘制不可见的组件...
现在,说了这么多……
如果您想在 BlurPanel
上绘制,您可以...在绘制 blurBuffer
之后绘制内容,因此您在其上绘制或在 BlurPanel
窗格中添加另一个组件,其中包含您要应用的绘图逻辑...
这是该概念的一个基本示例。这会在玻璃窗格上添加另一个面板,它可以根据需要绘制面板的自定义框架。
此示例使用个人库代码,仅作为概念的示例,而不是完全可运行的示例。
import core.ui.GlowEffectFactory;
import core.ui.GraphicsUtilities;
import core.util.ByteFormatter;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class TransparentTest
public static void main(String[] args)
new TransparentTest();
public TransparentTest()
EventQueue.invokeLater(new Runnable()
@Override
public void run()
try
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex)
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
);
public class TestPane extends JPanel
private BufferedImage background;
private BlurredGlassPane blurredGlassPane;
private InfoPane infoPane;
public TestPane()
try
background = ImageIO.read(new File("get your own image"));
catch (IOException ex)
ex.printStackTrace();
blurredGlassPane = new BlurredGlassPane();
blurredGlassPane.setLayout(new GridBagLayout());
infoPane = new InfoPane();
infoPane.setFile(new File("get your own image"));
blurredGlassPane.add(infoPane);
JButton click = new JButton("Click");
click.addActionListener(new ActionListener()
@Override
public void actionPerformed(ActionEvent e)
Window win = SwingUtilities.getWindowAncestor(TestPane.this);
if (win instanceof JFrame)
JFrame frame = (JFrame) win;
frame.setGlassPane(blurredGlassPane);
blurredGlassPane.setVisible(true);
);
setLayout(new GridBagLayout());
add(click);
@Override
public Dimension getPreferredSize()
return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight());
@Override
protected void paintComponent(Graphics g)
super.paintComponent(g);
if (background != null)
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
g2d.dispose();
public static class InfoPane extends JPanel
protected static final int RADIUS = 20;
protected static final int FRAME = 4;
protected static final int INSET = RADIUS + FRAME;
protected static final DateFormat DATE_FORMAT = DateFormat.getDateTimeInstance();
private JLabel name;
private JLabel path;
private JLabel length;
private JLabel lastModified;
private JLabel canExecute;
private JLabel canRead;
private JLabel canWrite;
private JLabel isDirectory;
private JLabel isHidden;
public InfoPane()
setBorder(new EmptyBorder(INSET, INSET, INSET, INSET));
setOpaque(false);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.anchor = GridBagConstraints.WEST;
gbc.gridwidth = GridBagConstraints.REMAINDER;
name = createLabel(Font.BOLD, 48);
add(name, gbc);
gbc.gridy++;
path = createLabel();
add(path, gbc);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.WEST;
length = createLabel();
lastModified = createLabel();
add(createLabel("Size: "), gbc);
gbc.gridx++;
gbc.insets = new Insets(0, 0, 0, 10);
add(length, gbc);
gbc.insets = new Insets(0, 0, 0, 0);
gbc.gridx++;
add(createLabel("Last Modified: "), gbc);
gbc.gridx++;
add(lastModified, gbc);
public JLabel createLabel(String text)
JLabel label = new JLabel(text);
label.setForeground(Color.WHITE);
return label;
public JLabel createLabel()
return createLabel("");
public JLabel createLabel(int style, float size)
JLabel label = createLabel();
label.setFont(label.getFont().deriveFont(style, size));
return label;
public void setFile(File file)
name.setText(file.getName());
try
path.setText(file.getParentFile().getCanonicalPath());
catch (IOException ex)
ex.printStackTrace();
length.setText(ByteFormatter.format(file.length()));
lastModified.setText(DATE_FORMAT.format(new Date(file.lastModified())));
file.canExecute();
file.canRead();
file.canWrite();
file.isDirectory();
file.isHidden();
@Override
protected void paintComponent(Graphics g)
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
GraphicsUtilities.applyQualityRenderingHints(g2d);
int width = getWidth() - 1;
int height = getHeight() - 1;
int buffer = FRAME / 2;
RoundRectangle2D base = new RoundRectangle2D.Double(buffer, buffer, width - FRAME, height - FRAME, RADIUS, RADIUS);
g2d.setColor(new Color(0, 0, 0, 128));
g2d.fill(base);
g2d.setColor(Color.WHITE);
g2d.setStroke(new BasicStroke(FRAME, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2d.draw(base);
g2d.dispose();
public class BlurredGlassPane extends JPanel
private BufferedImage background;
@Override
public void setVisible(boolean visible)
if (visible)
Container parent = SwingUtilities.getAncestorOfClass(JRootPane.class, this);
if (parent != null)
JRootPane rootPane = (JRootPane) parent;
BufferedImage img = new BufferedImage(rootPane.getWidth(), rootPane.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
rootPane.printAll(g2d);
g2d.dispose();
background = GlowEffectFactory.generateBlur(img, 40);
super.setVisible(visible);
@Override
protected void paintComponent(Graphics g)
super.paintComponent(g);
g.drawImage(background, 0, 0, this);
【讨论】:
感谢您给我演示,但我对 RenderingHints 和 Graphics2D 中的许多东西没有太多了解,因为 java 文档没有提供关于 RenderingHints 及其常量的太多信息。我需要时间才能理解您的答案,但无论我理解什么,都可以告诉我它是对还是错? 1.创建一个包含背景图像或渐变的面板 2.创建它的模糊效果并同时创建细节面板(透明矩形)。 3. 在该面板上绘制透明矩形 4. 最后在根窗格上绘制图像。jf.getGlassPane().setVisible(false); glassPanel = new GlassPanel(); jf.getGlassPane().setVisible(true);
在这些声明中,我试图更改 glasspane 的内容,并且正如摆动规则所说,不要尝试更改任何可见组件的内容。这就是我尝试做这些事情的原因。
并非如此。 1.创建背景面板(图像/渐变)。 2. 创建模糊图像。 3. 创建可以绘制模糊图像的面板。 4. 将任何内容添加到“模糊面板”。模糊面板必须出现在背景面板上方,并且所有内容都必须出现在其上方...
这可能是一个愚蠢的答案,但jf.setGlassPane(glassPanel)
将glassPanel
设置为glassPane
还是仅在根窗格上添加glassPanel
做什么??
jf.setGlassPane(glassPanel);
设置将用作根窗格“玻璃窗格”并由jf.getGlassPane()
返回的组件。 glassPanel = new GlassPanel();
仅更改 glassPanel
的引用,而不是 JFrame
正在使用的引用...以上是关于在jframe中的模糊背景上创建一个透明矩形的主要内容,如果未能解决你的问题,请参考以下文章