I am having problem in creating an transparent rectangle over blurred background. I am trying to do this task on glasspane. Here is my code snippet.
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);
}
where, backBuffer and blurBuffer are objects of BufferedImage & jf = JFrame, alpha is used for opacity.
The above method create an Blurred Effect very well.
Here is the code which creates an transparent rectangle over Panel
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();
}
Now where I stuck is how do I paint the blurred effect and transparent rectangle at the same time.
I didn't posted whole code over here, if anyone wish to see the code here the link.
And here is an desired image of sample output. Thanks in advance.
I'm trying to make heads and tails of your code...
You fail to call super.paintComponent...this could lead you into a same serious issues if you're not careful. General rule of thumb, just call it ;)
Be careful when modifiying the state of a Graphics context, for example...
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Will affect ALL components painted after this one and could cause some interesting graphical glitches you weren't expecting...
jf.getGlassPane().setVisible(false);
glassPanel = new GlassPanel();
jf.getGlassPane().setVisible(true);
Seems pointless, as the component set using jf.setGlassPane(glassPanel); will still be the component that is made visible when you call jf.getGlassPane().setVisible(true);. This also means that the GlassPane component is never used...
Checking isVisible in paintComponent is pointless, as Swing is clever enough to know not to paint invisible components...
Now, having said all that...
If you wanted to paint on top of the BlurPanel you would either...paint content after the blurBuffer is drawn, so you are drawing ontop of it OR add another component onto the BlurPanel pane which contains the drawing logic you want to apply...
This is a basic example of that concept. This adds another panel onto the glass pane which paints the custom frame of the panel as I want.
This example uses personal library code and is intended as an example of the concept alone, not a completely runnable example.
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);
}
}
}
Related
After learning that dispose() should be called on Graphics/Graphics2D object after use, I went about changing my game to incorporate this.
When I added g2d.dispose() in overridden paintComponent(Graphics g) of JPanel, my components which I added (extensions of JLabel class) where not rendered I was able to still click on them etc but they would not be painted.
I tested with a normal JLabel and JButton with same effect (though JButton is rendered when mouse is over it).
So my question is why does this happen?
Here is an SSCCE to demonstrate:
after uncommenting call to dispose() in paintComponent of MainMenuPanel class:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public Test() {
try {
initComponents();
} catch (Exception ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
private void initComponents() throws Exception {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
MainMenuPanel mmp = new MainMenuPanel();
frame.add(mmp);
frame.pack();
frame.setVisible(true);
}
}
class MainMenuPanel extends JPanel {
//create labels for Main Menu
private PopUpJLabel versusesModeLabel;
private PopUpJLabel singlePlayerModeLabel;
private PopUpJLabel optionsLabel;
private PopUpJLabel helpLabel;
private PopUpJLabel aboutLabel;
//create variable to hold background
private Image background;
private Dimension preferredDimensions;
public static String gameType;
public static final String SINGLE_PLAYER = "Single Player", VERSUS_MODE = "VS Mode";
/**
* Default constructor to initialize double buffered JPanel with
* GridBagLayout
*/
public MainMenuPanel() {
super(new GridBagLayout(), true);
try {
initComponents();
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "Could not load main menu background!", "Main Menu Error: 0x004", JOptionPane.ERROR_MESSAGE);
System.exit(4);
}
}
/*
* Create JPanel and its components
*/
private void initComponents() throws Exception {
//set prefered size of JPanel
preferredDimensions = new Dimension(800, 600);
background = scaleImage(800, 600, ImageIO.read(new URL("http://photos.appleinsider.com/12.08.30-Java.jpg")));
//create label instances
singlePlayerModeLabel = new PopUpJLabel("Single Player Mode");
singlePlayerModeLabel.setEnabled(false);
versusesModeLabel = new PopUpJLabel("Versus Mode");
optionsLabel = new PopUpJLabel("Options");
helpLabel = new PopUpJLabel("Help");
aboutLabel = new PopUpJLabel("About");
//create new constraints for gridbag
GridBagConstraints gc = new GridBagConstraints();
gc.fill = GridBagConstraints.HORIZONTAL;
gc.ipady = 50;//vertical spacing
//add newGameLabel to panel with constraints
gc.gridx = 0;
gc.gridy = 0;
add(singlePlayerModeLabel, gc);
gc.gridy = 1;
add(versusesModeLabel, gc);
//add optionsLabel to panel with constraints (x is the same)
gc.gridy = 2;
add(optionsLabel, gc);
//add helpLabel to panel with constraints (x is the same)
gc.gridy = 3;
add(helpLabel, gc);
//add aboutLabel to panel with constraints (x is the same)
gc.gridy = 4;
add(aboutLabel, gc);
}
public static BufferedImage scaleImage(int w, int h, BufferedImage img) throws Exception {
BufferedImage bi;
//bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
bi = new BufferedImage(w, h, img.getType());
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(img, 0, 0, w, h, null);
g2d.dispose();
return bi;
}
/*
* Will return the preffered size of JPanel
*/
#Override
public Dimension getPreferredSize() {
return preferredDimensions;
}
/*
* Will draw the background to JPanel with anti-aliasing on and quality rendering
*/
#Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
//convert graphics object to graphics2d object
Graphics2D g2d = (Graphics2D) grphcs;
//set anti-aliasing on and rendering etc
//GamePanel.applyRenderHints(g2d);
//draw the image as the background
g2d.drawImage(background, 0, 0, null);
//g2d.dispose();//if I uncomment this no LAbels will be shown
}
}
class PopUpJLabel extends JLabel {
public final static Font defaultFont = new Font("Arial", Font.PLAIN, 50);
public final static Font hoverFont = new Font("Arial", Font.BOLD, 70);
PopUpJLabel(String text) {
super(text);
setHorizontalAlignment(JLabel.CENTER);
setForeground(Color.ORANGE);
setFont(defaultFont);
//allow component to be focusable
setFocusable(true);
//add focus adapter to change fints when focus is gained or lost (used for transversing labels with keys)
addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent fe) {
super.focusGained(fe);
if (isEnabled()) {
setFont(getHoverFont());
}
}
#Override
public void focusLost(FocusEvent fe) {
super.focusLost(fe);
setFont(getDefaultFont());
}
});
addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent me) {
super.mouseEntered(me);
if (isEnabled()) {
setFont(getHoverFont());
}
//call for focus mouse is over this component
requestFocusInWindow();
}
});
}
Font getDefaultFont() {
return defaultFont;
}
Font getHoverFont() {
return hoverFont;
}
}
The thing is that the Graphics context you are using in paintComponent is created and provided by the caller (the framework), which is also responsible for disposing of it.
You only need to dispose of Graphics when you actually create it yourself (for example by calling Component.getGraphics()). In your case, you're not creating it, you're just casting it, so do not call dispose in this case.
Because .dispose() releases your resources. Yes, everything.
The Problem is I make a class that extends JPanel with gradient Color background but the problem is when I am getting the background of it to use it to other component is I cannot get the color of it. I want to set the background color of components same to other components
I had tried to use .getBackground(); But it doesn't work on it. what should I do so that I can get the background of it?
import javax.swing.*;
import java.awt.*;
public class GradientPaintDemo extends JPanel {
private static final int scale = 2;
private static final Color c1 = Color.decode("#00F260");
private static final Color c2 = Color.decode("#0575E6");
private static final int size = (c2.getRed() - c1.getRed()) * scale;
#Override
public Dimension getPreferredSize() {
return new Dimension(size, size);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
int w = getWidth();
int h = getHeight();
GradientPaint gp = new GradientPaint(20, 0, c1, 20, h, c2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, w, h);
}
}
then when in my Main Class
GradientPaintDemo gpd = new GradientPaintDemo();
JPanel panel1 = new JPanel();
gpd.add(panel1);
panel.getBackground();
I want that to have only one background on all of my panels and buttons I want to look like this image below
At a "guess" I would say you need to make the child component transparent, using panel1.setOpaque(false), so the parent will show through it.
Also, at a "guess", the use of size in your getPreferredSize method could be causing you issues. Instead, I'd set the component's default layout manager to BorderLayout and let the child dictate the required size.
For example, opaque...
Transparent...
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class Test extends JFrame {
public static void main(String[] args) {
new Test();
}
public Test() throws HeadlessException {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
GradientPaintDemo gpd = new GradientPaintDemo();
gpd.setBorder(new EmptyBorder(20, 20, 20, 20));
JPanel panel = new JPanel();
panel.setBorder(new EmptyBorder(20, 20, 20, 20));
panel.add(new JLabel("This is a test"));
panel.setOpaque(false);
gpd.add(panel);
frame.add(gpd);
frame.pack();
frame.setVisible(true);
}
});
}
public static class GradientPaintDemo extends JPanel {
private static final int scale = 2;
private static final Color c1 = Color.decode("#00F260");
private static final Color c2 = Color.decode("#0575E6");
private static final int size = (c2.getRed() - c1.getRed()) * scale;
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
int w = getWidth();
int h = getHeight();
GradientPaint gp = new GradientPaint(20, 0, c1, 20, h, c2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, w, h);
}
}
}
After learning that dispose() should be called on Graphics/Graphics2D object after use, I went about changing my game to incorporate this.
When I added g2d.dispose() in overridden paintComponent(Graphics g) of JPanel, my components which I added (extensions of JLabel class) where not rendered I was able to still click on them etc but they would not be painted.
I tested with a normal JLabel and JButton with same effect (though JButton is rendered when mouse is over it).
So my question is why does this happen?
Here is an SSCCE to demonstrate:
after uncommenting call to dispose() in paintComponent of MainMenuPanel class:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public Test() {
try {
initComponents();
} catch (Exception ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
private void initComponents() throws Exception {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
MainMenuPanel mmp = new MainMenuPanel();
frame.add(mmp);
frame.pack();
frame.setVisible(true);
}
}
class MainMenuPanel extends JPanel {
//create labels for Main Menu
private PopUpJLabel versusesModeLabel;
private PopUpJLabel singlePlayerModeLabel;
private PopUpJLabel optionsLabel;
private PopUpJLabel helpLabel;
private PopUpJLabel aboutLabel;
//create variable to hold background
private Image background;
private Dimension preferredDimensions;
public static String gameType;
public static final String SINGLE_PLAYER = "Single Player", VERSUS_MODE = "VS Mode";
/**
* Default constructor to initialize double buffered JPanel with
* GridBagLayout
*/
public MainMenuPanel() {
super(new GridBagLayout(), true);
try {
initComponents();
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "Could not load main menu background!", "Main Menu Error: 0x004", JOptionPane.ERROR_MESSAGE);
System.exit(4);
}
}
/*
* Create JPanel and its components
*/
private void initComponents() throws Exception {
//set prefered size of JPanel
preferredDimensions = new Dimension(800, 600);
background = scaleImage(800, 600, ImageIO.read(new URL("http://photos.appleinsider.com/12.08.30-Java.jpg")));
//create label instances
singlePlayerModeLabel = new PopUpJLabel("Single Player Mode");
singlePlayerModeLabel.setEnabled(false);
versusesModeLabel = new PopUpJLabel("Versus Mode");
optionsLabel = new PopUpJLabel("Options");
helpLabel = new PopUpJLabel("Help");
aboutLabel = new PopUpJLabel("About");
//create new constraints for gridbag
GridBagConstraints gc = new GridBagConstraints();
gc.fill = GridBagConstraints.HORIZONTAL;
gc.ipady = 50;//vertical spacing
//add newGameLabel to panel with constraints
gc.gridx = 0;
gc.gridy = 0;
add(singlePlayerModeLabel, gc);
gc.gridy = 1;
add(versusesModeLabel, gc);
//add optionsLabel to panel with constraints (x is the same)
gc.gridy = 2;
add(optionsLabel, gc);
//add helpLabel to panel with constraints (x is the same)
gc.gridy = 3;
add(helpLabel, gc);
//add aboutLabel to panel with constraints (x is the same)
gc.gridy = 4;
add(aboutLabel, gc);
}
public static BufferedImage scaleImage(int w, int h, BufferedImage img) throws Exception {
BufferedImage bi;
//bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
bi = new BufferedImage(w, h, img.getType());
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(img, 0, 0, w, h, null);
g2d.dispose();
return bi;
}
/*
* Will return the preffered size of JPanel
*/
#Override
public Dimension getPreferredSize() {
return preferredDimensions;
}
/*
* Will draw the background to JPanel with anti-aliasing on and quality rendering
*/
#Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
//convert graphics object to graphics2d object
Graphics2D g2d = (Graphics2D) grphcs;
//set anti-aliasing on and rendering etc
//GamePanel.applyRenderHints(g2d);
//draw the image as the background
g2d.drawImage(background, 0, 0, null);
//g2d.dispose();//if I uncomment this no LAbels will be shown
}
}
class PopUpJLabel extends JLabel {
public final static Font defaultFont = new Font("Arial", Font.PLAIN, 50);
public final static Font hoverFont = new Font("Arial", Font.BOLD, 70);
PopUpJLabel(String text) {
super(text);
setHorizontalAlignment(JLabel.CENTER);
setForeground(Color.ORANGE);
setFont(defaultFont);
//allow component to be focusable
setFocusable(true);
//add focus adapter to change fints when focus is gained or lost (used for transversing labels with keys)
addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent fe) {
super.focusGained(fe);
if (isEnabled()) {
setFont(getHoverFont());
}
}
#Override
public void focusLost(FocusEvent fe) {
super.focusLost(fe);
setFont(getDefaultFont());
}
});
addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent me) {
super.mouseEntered(me);
if (isEnabled()) {
setFont(getHoverFont());
}
//call for focus mouse is over this component
requestFocusInWindow();
}
});
}
Font getDefaultFont() {
return defaultFont;
}
Font getHoverFont() {
return hoverFont;
}
}
The thing is that the Graphics context you are using in paintComponent is created and provided by the caller (the framework), which is also responsible for disposing of it.
You only need to dispose of Graphics when you actually create it yourself (for example by calling Component.getGraphics()). In your case, you're not creating it, you're just casting it, so do not call dispose in this case.
Because .dispose() releases your resources. Yes, everything.
I am creating an program in which I can draw a map and add different roads etc to it. I have planned to add the map terrain on one jpanel, and the roads etc on another, on top of each other. But I can't get them to work. I don't know how to add multiple jpanels completely on top of each other and making them all able to draw.
The basic approach to this problem would be to use a JLayeredPane and something like GridBagLayout.
The JLayeredPane will give you some better control over the z-deepthness of the various layers and the GridBagLayout will allow you to lay components over each other as you need.
You could also take a look at OverlayoutLayout, but never having used it, I can't comment.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MapLayers {
public static void main(String[] args) {
new MapLayers();
}
public MapLayers() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
MapPane mapPane = new MapPane();
try {
mapPane.addLayer(new ImageLayer(ImageIO.read(new File("Ponie.png")), 360, 10));
mapPane.addLayer(new ImageLayer(ImageIO.read(new File("Layer01.png")), 0, 0));
} catch (IOException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(mapPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ImageLayer extends JComponent {
private Image bg;
private int xOffset;
private int yOffset;
public ImageLayer(Image image, int x, int y) {
bg = image;
xOffset = x;
yOffset = y;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bg != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(bg, xOffset, yOffset, this);
g2d.dispose();
}
}
}
public class MapPane extends JLayeredPane {
private BufferedImage bg;
public MapPane() {
try {
bg = ImageIO.read(new File("PirateMap.jpg"));
} catch (IOException exp) {
exp.printStackTrace();
}
setLayout(new GridBagLayout());
}
public void addLayer(JComponent layer) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
add(layer, gbc);
}
#Override
public Dimension getPreferredSize() {
return bg == null ? new Dimension(200, 200) : new Dimension(bg.getWidth(), bg.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bg != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - bg.getWidth()) / 2;
int y = (getHeight()- bg.getHeight()) / 2;
g2d.drawImage(bg, x, y, this);
g2d.dispose();
}
}
}
}
Take a look at How to use LayeredPanes for some more details
Are you intending to make the JPanels transparent? You can call setOpaque(false), which will prevent the panel from flooding a background rectangle. There is some useful information on stacking panes in the Swing tutorial.
I am developing an app using Swing. While user interact with the app, help data may become available in a closed section of the screen, and I'd like to draw a small arrow pointing to that section when this happens.
To do this, I extended a JPanel and added it as the glasspane of the app jframe. The name of the custom glass pane class is AlertGlassPane.
The AlertGlassPane do this: waits until new help data is available. When this happens and the help section is closed, it finds the position of the help section on the screen and then draws an animated arrow at its side.
To draw the arrow I extended the method paintComponent of the glass pane.
To animate the arrow I created a small thread that loop every 100 ms, calling repaint on the glass pane.
The problem: Java ignores my drawing... if a trigger the start of the animation and stand still, nothing happens. No drawing is shown on the app.
I know that the loop is running and paintComponent is being called, but the custom paint is not taking effect.
But if I move the mouse over the region where the arrow should be rendered, it does! But just when the mouse is moving. If a stop move the mouse, the animation stops too, and the arrow freezes on the last position before the mouse stop (or leaves the area).
I tried a lot of things (as set the clip region of the drawing, for example), but nothing seems to work. The only thing that works was when I called by mistake repaint from inside the paintComponent.
At this moment I'm looking for a way to comunicate to the rendering system that a givem region of my glasspane needs to be repainted (repaint(x, y, w, h) didn't work...). Maybe moving the custom rendering to a JLabel and then adding this label to the glasspane? I don't like this approach...
I'll try to clean up the code before post a snippet here. Would it help?
Thanks in advance!
snnipet:
package br.com.r4j.test;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.image.BufferedImage;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.text.JTextComponent;
/**
*
* #author
*/
public class TestGlassPaneAnimation extends JPanel
{
private static TestGlassPaneAnimation gvp = new TestGlassPaneAnimation();
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
JFrame f = new JFrame("Anitest in glass");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//f.setResizable(false);
f.setLayout(new GridLayout(5, 3));
f.add(new JLabel("First Name :"));
f.add(new JTextField(20));
f.add(new JLabel("Last Name :"));
f.add(new JTextField(20));
f.add(new JLabel("Phone Number :"));
f.add(new JTextField(20));
f.add(new JLabel("Email:"));
f.add(new JTextField(20));
f.add(new JLabel("Address :"));
f.add(new JTextField(20));
JButton btnStart = new JButton("Click me, please!");
f.add(btnStart);
btnStart.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
gvp.startAnimation();
}
});
f.setGlassPane(gvp);
f.pack();
f.setVisible(true);
gvp.setVisible(true);
}
});
}
private BufferedImage icon;
private boolean animate = false;
private long timeStart = 0;
private Thread thrLastActive = null;
public TestGlassPaneAnimation()
{
setLayout(null);//this is the exception to the rule case a layoutmanager might make setting Jlabel co-ords harder
setOpaque(false);
Icon icon1 = UIManager.getIcon("OptionPane.warningIcon");
int imgW = icon1.getIconWidth();
int imgH = icon1.getIconHeight();
this.icon = ImageUtilities.getBufferedImageOfIcon(icon1, imgW, imgH);
this.animate = false;
}
public void startAnimation()
{
this.animate = true;
this.timeStart = (new Date()).getTime();
if (this.thrLastActive != null)
this.thrLastActive.interrupt();
this.thrLastActive = new Thread(new Runnable()
{
public void run()
{
try
{
while (true)
{
// int x = 250, y = 250;
// int width = 60, height = 60;
Thread.currentThread().sleep(100);
// frmRoot.invalidate();
// repaint(x, y, width, height);
repaint(new Rectangle(x, y, width, height));
// repaint(new Rectangle(10, 10, 2000, 2000));
// repaint();
// paintComponent(getGraphics());
}
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
this.thrLastActive.start();
}
protected void paintComponent(Graphics g)
{
try
{
// enables anti-aliasing
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
java.awt.Composite composite = g2.getComposite();
System.err.println("b1: " + g.getClipBounds());
if (this.animate)
{
long timeSpent = (new Date()).getTime() - timeStart;
int x = 10, y = 150;
int width = 60, height = 60;
float maxAlpha = 0.8f;
x += (-100*Math.sin(5*2*Math.PI*timeSpent/10000)+50)/15;
System.err.println("painting::x: " + x + ", y: " + y + ", sin: " + (Math.sin(6*2*Math.PI*timeSpent/10000)));
// g.setClip(x-10, y-10, width, height);
System.err.println("b2: " + g.getClipBounds());
AlphaComposite alpha2 = AlphaComposite.SrcOver.derive(maxAlpha);
g2.setComposite(alpha2);
g2.drawImage(this.icon, x, y, null);
g2.setComposite(composite);
g2.setComposite(composite);
}
}
catch (Throwable e)
{
System.err.println("Errr!");
e.printStackTrace();
}
}
}
class ImageUtilities {
public static BufferedImage resize(BufferedImage image, int width, int height) {
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(image, 0, 0, width, height, null);
g2d.dispose();
return bi;
}
public static BufferedImage getBufferedImageOfIcon(Icon icon, int imgW, int imgH) {
BufferedImage img = new BufferedImage(imgW, imgH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D) img.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
icon.paintIcon(null, g2d, 0, 0);
g2d.dispose();
return img;
}
}
Hmm not sure exactly whats going on with the snippet you gave but as it looks like it was taken from mine I wrote another example (I had to change a 1 or 2 lines of code in showWarningIcon(Component c) and refreshLocations() methods but nothing major:
If anything except david is typed and the button (click me, please) clicked it will show this:
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class TestGlassPaneAnimation {
private static GlassValidationPane gvp = new GlassValidationPane();
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame("Anitest in glass");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//f.setResizable(false);
f.setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
gc.fill = GridBagConstraints.HORIZONTAL;
gc.weightx = 1;
gc.weighty = 1;
gc.insets = new Insets(15, 15, 15, 15);//give some space so icon doesnt cover components when shown
gc.gridx = 0;
gc.gridy = 0;
f.add(new JLabel("First Name:"), gc);
final JTextField jtf = new JTextField(20);
gc.gridx = 1;
f.add(jtf, gc);
gc.gridx = 0;
gc.gridy = 1;
f.add(new JLabel("Surname:"), gc);
final JTextField jtf2 = new JTextField(20);
gc.gridx = 1;
f.add(jtf2, gc);
JButton btnStart = new JButton("Click me, please!");
gc.gridx = 2;
f.add(btnStart, gc);
btnStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!jtf.getText().equalsIgnoreCase("david")) {
gvp.showWarningIcon(jtf);
}
}
});
f.addComponentListener(new ComponentAdapter() {//so wjen frame is resized icons follow
#Override
public void componentResized(ComponentEvent ce) {
super.componentResized(ce);
gvp.refreshLocations();
}
});
f.setGlassPane(gvp);
f.pack();
f.setVisible(true);
gvp.setVisible(true);
}
});
}
}
class GlassValidationPane extends JPanel {
private HashMap<Component, JLabel> warningLabels = new HashMap<>();
private ImageIcon warningIcon;
public GlassValidationPane() {
setLayout(null);//this is the exception to the rule case a layoutmanager might make setting Jlabel co-ords harder
setOpaque(false);
Icon icon = UIManager.getIcon("OptionPane.warningIcon");
int imgW = icon.getIconWidth();
int imgH = icon.getIconHeight();
BufferedImage img = ImageUtilities.getBufferedImageOfIcon(icon, imgW, imgH);
warningIcon = new ImageIcon(ImageUtilities.resize(img, 24, 24));
}
void showWarningIcon(Component c) {
if (warningLabels.containsKey(c)) {
return;
}
JLabel label = new JLabel();
label.setIcon(warningIcon);
//int x=c.getX();//this will make it insode the component
int x = c.getX() - warningIcon.getIconWidth();//this makes it appear outside/next to component if space
int y = c.getY();
label.setBounds(x, y, warningIcon.getIconWidth(), warningIcon.getIconHeight());
add(label);
revalidate();
repaint();
warningLabels.put(c, label);
}
public void removeWarningIcon(Component c) {
for (Map.Entry<Component, JLabel> entry : warningLabels.entrySet()) {
Component component = entry.getKey();
JLabel jLabel = entry.getValue();
if (component == c) {
remove(jLabel);
revalidate();
repaint();
break;
}
}
warningLabels.remove(c);
}
public void refreshLocations() {
for (Map.Entry<Component, JLabel> entry : warningLabels.entrySet()) {
Component c = entry.getKey();
JLabel label = entry.getValue();
//int x=c.getX();//this will make it insode the component
int x = c.getX() - label.getIcon().getIconWidth();//this makes it appear outside/next to component
int y = c.getY();
label.setBounds(x, y, label.getIcon().getIconWidth(), label.getIcon().getIconHeight());
revalidate();
repaint();
}
}
}
class ImageUtilities {
public static BufferedImage resize(BufferedImage image, int width, int height) {
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(image, 0, 0, width, height, null);
g2d.dispose();
return bi;
}
public static BufferedImage getBufferedImageOfIcon(Icon icon, int imgW, int imgH) {
BufferedImage img = new BufferedImage(imgW, imgH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D) img.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
icon.paintIcon(null, g2d, 0, 0);
g2d.dispose();
return img;
}
}
If you are looking for a more mature library have a look at JXLayer - Validation Overlays and Validation overlays using glass pane.
Also might want to have a read here which shows many ways of validating a textfields data (other than button press) like DocumentFilter and InputVerifier etc.