I created one JFrame. and set layout shown in below code
this.setLayout(new GridLayout());
JPanel panel=new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(new PicturePanel1());
JTabbedPane jtp=new JTabbedPane();
jtp.addTab("show Images", panel);
jtp.addTab("Compare Image", new JButton());
this.add(jtp);
I created another class that draws Images from particular location.
protected void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D g2 = (Graphics2D) g;
int k = 20,y=10;
for (int j = 0; j <= listOfFiles.length - 1; j++) {
g2.drawImage(b[j], k, y, 100, 100, null);
// add(new javax.swing.JCheckBox());
k = k + 120;
if(k>=960)
{
k=20;
y=y+120;
}
}
Its working fine. I want to delete Images when user clicks on particular Image.
This is my output window. I want to delete Image from list.
Here is an example I made (bored and tired of studying :)). It is by no means the best just a quick thing to show you an example, click the image you want to delete and then press the delete button or DEL to remove and image from the panel:
When app starts up (orange just shows focused label for hovering):
Image to delete is selected by clicking on the Label (Border becomes green highlighted and will remain this way until another label is clicked):
After delete button or key is pressed:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
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.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
public class JavaApplication5 {
public static void main(String[] args) {
createAndShowJFrame();
}
public static void createAndShowJFrame() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = createJFrame();
frame.setVisible(true);
}
});
}
private static JFrame createJFrame() {
JFrame frame = new JFrame();
//frame.setResizable(false);//make it un-resizeable
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Test");
ArrayList<BufferedImage> images = null;
try {
images = getImagesArrayList();
} catch (Exception ex) {
ex.printStackTrace();
}
final ImageViewPanel imageViewPanel = new ImageViewPanel(images);
JScrollPane jsp = new JScrollPane(imageViewPanel);
jsp.setPreferredSize(new Dimension(400, 400));
frame.add(jsp);
JPanel controlPanel = new JPanel();
JButton addLabelButton = new JButton("Delete Selected Image");
addLabelButton.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
imageViewPanel.removeFocusedImageLabel();
}
});
controlPanel.add(addLabelButton);
frame.add(controlPanel, BorderLayout.SOUTH);
frame.pack();
return frame;
}
private static ArrayList<BufferedImage> getImagesArrayList() throws Exception {
ArrayList<BufferedImage> images = new ArrayList<>();
images.add(resize(ImageIO.read(new URL("http://icons.iconarchive.com/icons/deleket/sleek-xp-software/256/Yahoo-Messenger-icon.png")), 100, 100));
images.add(resize(ImageIO.read(new URL("https://upload.wikimedia.org/wikipedia/commons/6/64/Gnu_meditate_levitate.png")), 100, 100));
return images;
}
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;
}
}
class ImageViewPanel extends JPanel {
JLabel NO_IMAGES = new JLabel("No Images");
ArrayList<BufferedImage> images;
ArrayList<MyLabel> imageLabels;
public ImageViewPanel(ArrayList<BufferedImage> images) {
this.images = images;
imageLabels = new ArrayList<>();
for (BufferedImage bi : images) {
imageLabels.add(new MyLabel(new ImageIcon(bi), this));
}
layoutLabels();
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0, true), "Delete pressed");
getActionMap().put("Delete pressed", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
removeFocusedImageLabel();
}
});
}
void removeFocusedImageLabel() {
if (focusedLabel == null) {
return;
}
imageLabels.remove(focusedLabel);
remove(focusedLabel);
layoutLabels();
}
private void layoutLabels() {
if (imageLabels.isEmpty()) {
add(NO_IMAGES);
} else {
remove(NO_IMAGES);
for (JLabel il : imageLabels) {
add(il);
}
}
revalidate();
repaint();
}
private MyLabel focusedLabel;
void setFocusedLabel(MyLabel labelToFocus) {
if (focusedLabel != null) {
focusedLabel.setBorder(null);
focusedLabel.setClicked(false);
}
focusedLabel = labelToFocus;
focusedLabel.setBorder(new LineBorder(Color.GREEN));
}
}
class MyLabel extends JLabel {
private final ImageViewPanel imageViewPanel;
private boolean clicked = false;
public MyLabel(Icon image, ImageViewPanel imageViewPanel) {
super(image);
this.imageViewPanel = imageViewPanel;
initLabel();
}
public MyLabel(String text, ImageViewPanel imageViewPanel) {
super(text);
this.imageViewPanel = imageViewPanel;
initLabel();
}
private void initLabel() {
setFocusable(true);
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
clicked = true;
imageViewPanel.setFocusedLabel(MyLabel.this);
}
#Override
public void mouseEntered(MouseEvent me) {
super.mouseEntered(me);
if (clicked) {
return;
}
setBorder(new LineBorder(Color.ORANGE));
//call for focus mouse is over this component
requestFocusInWindow();
}
});
addFocusListener(new FocusAdapter() {
#Override
public void focusLost(FocusEvent e) {
super.focusLost(e);
if (clicked) {
return;
}
setBorder(null);
}
});
}
public void setClicked(boolean clicked) {
this.clicked = clicked;
}
public boolean isClicked() {
return clicked;
}
}
simply find the location (x, and y) and the size(width, and height) of image, then with the Graphics object (g2) fill a rectangle over the image drawn, like this
g2.setColor(this.getBackground());//set the color you want to clear the bound this point to JFrame/JPanel
g2.fillRect(x, y, width, height);
where x and y where is the location that images is located, and width and height are size of the picture
Related
I am trying to make a portion of my screen appear blurry. I grab pixel colors out of a BufferedImage where I saved a capture of the screen and draw the pixels again as bigger squares. But this only works when the paint method is called the first time, after that the affected pixels always stay the same even when the content of the screen updates. So it seems that even though the canvas is refreshed at the beginning of the paint method, the robot still sees the screen as it was previously...
#Override public void paintComponent(Graphics g) {
super.paintComponent(g);
screen = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
int gap = 10; int width = 1920;
for (int r = 120; r <= 420; r += gap) {
for (int c = 500; c <= width - 500; c += gap) {
g.setColor(new Color(screen.getRGB(c, r)));
g.fillRect(c, r, gap, gap);
}
}
}
I tried clearing the painted area using clearRect() and sleeping the Thread at different positions, but it didn't work. Where do I need to put the createScreenCapture() so the painting actually updates?
This is the whole class:
import java.awt.AWTException;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Transparent extends JPanel implements Runnable {
private JFrame frame;
private Robot robot;
private BufferedImage screen;
public static void main(String[] args) {
new Transparent();
}
public Transparent() {
try {
robot = new Robot();
} catch (AWTException ex) {
ex.printStackTrace();
}
frame = new JFrame();
init();
frame.add(this);
frame.setUndecorated(true);
frame.setBackground(new Color(0, true));
frame.setAlwaysOnTop(true);
frame.setSize(1920, 1080);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
new Thread(this).start();
}
public void init() {
setBackground(new Color(0, true));
setOpaque(false);
}
#Override public void paintComponent(Graphics g) {
super.paintComponent(g);
screen = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
int gap = 5; int width = 1920;
for (int r = 120; r <= 420; r += gap) {
for (int c = 500; c <= width - 500; c += gap) {
g.setColor(new Color(screen.getRGB(c, r)));
g.fillRect(c, r, gap, gap);
}
}
}
#Override public void run() {
while (true) {
repaint();
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
A number of things pop out at me...
You seem to be capturing the who screen, but are't taking into account were the window may actually be positioned and what area it might be covering
When you capture the screen, you component is going to be on it...
Now, this is a very simple example. I demonstrates how to convert the area of your panel to the screen coordinates and capture only that area. It does this by first hiding the window and then taking a snap shot of it before re-showing the window and painting the resulting snap-shot...
import com.jhlabs.image.GaussianFilter;
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Transparency;
import java.awt.Window;
import java.awt.event.HierarchyBoundsAdapter;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
try {
JPanel outter = new JPanel(new BorderLayout());
outter.setBorder(new EmptyBorder(20, 20, 20, 20));
outter.add(new TestPane());
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(outter);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (AWTException | HeadlessException exp) {
exp.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
private Robot bot;
private BufferedImage snapShot;
private Point lastSnapShot;
public TestPane() throws AWTException {
bot = new Robot();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void updateSnapshot() {
Rectangle bounds = getBounds();
Point p = new Point(0, 0);
SwingUtilities.convertPointToScreen(p, this);
bounds.setLocation(p);
if (lastSnapShot == null || !lastSnapShot.equals(p)) {
lastSnapShot = p;
Window window = SwingUtilities.getWindowAncestor(this);
window.addHierarchyListener(new HierarchyListener() {
#Override
public void hierarchyChanged(HierarchyEvent e) {
if (!window.isVisible()) {
e.getComponent().removeHierarchyListener(this);
snapShot = bot.createScreenCapture(bounds);
snapShot = generateBlur(snapShot, 10);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
window.setVisible(true);
}
});
}
}
});
window.setVisible(false);
}
}
public BufferedImage generateBlur(BufferedImage imgSource, int size) {
GaussianFilter filter = new GaussianFilter(size);
int imgWidth = imgSource.getWidth();
int imgHeight = imgSource.getHeight();
BufferedImage imgBlur = createCompatibleImage(imgWidth, imgHeight, Transparency.OPAQUE);
Graphics2D g2 = imgBlur.createGraphics();
g2.drawImage(imgSource, 0, 0, null);
g2.dispose();
imgBlur = filter.filter(imgBlur, null);
return imgBlur;
}
public BufferedImage createCompatibleImage(int width, int height, int transparency) {
GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
BufferedImage image = gc.createCompatibleImage(width, height, transparency);
image.coerceData(true);
return image;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (snapShot == null) {
updateSnapshot();
}
int x = 0;
int y = 0;
g2d.drawImage(snapShot, 0, 0, this);
g2d.dispose();
}
}
}
This example takes advantage of JH Lab's Filters, cause I'm to lazy to create my own...
I want to be able to click on a JTextArea and drag it around my JPanel. I'm not sure the method on doing so. What I'm trying to do is change the x,y coordinates of the JTextArea as it is dragged, I'm not dragging a JTextArea above or below another. Just around on the screen, similar to moving Text Boxes in a program like Microsoft PowerPoint
The only method I can think of is using a MouseListener but I'm wondering if there is an easier way to implement it other than detecting a hover/press/drag on the JTextArea. Any ideas on how I can start?
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class UMLEditor {
public static void main(String[] args) {
JFrame frame = new UMLWindow();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(30, 30, 1000, 700);
frame.getContentPane().setBackground(Color.white);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class UMLWindow extends JFrame {
Canvas canvas = new Canvas();
private static final long serialVersionUID = 1L;
public UMLWindow() {
addMenus();
}
public void addMenus() {
getContentPane().add(canvas);
JMenuBar menubar = new JMenuBar();
JMenuItem newTextBox = new JMenuItem("New Text Box");
newTextBox.setMnemonic(KeyEvent.VK_E);
newTextBox.setToolTipText("Exit application");
newTextBox.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
canvas.addTextBox();
}
});
menubar.add(newTextBox);
setJMenuBar(menubar);
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
class Canvas extends JPanel {
JTextArea commentTextArea = new JTextArea(10, 10);
public Canvas() {
this.setOpaque(true);
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
public void addTextBox() {
commentTextArea.setLineWrap(true);
commentTextArea.setWrapStyleWord(true);
commentTextArea.setVisible(true);
commentTextArea.setLocation(0, 0);
this.add(commentTextArea);
commentTextArea.setBounds(0, 0, 100, 100);
revalidate();
repaint();
}
class MyMouseAdapter extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
}
}
}
You don't really want to try and "drag" on JTextComponents, they already have functionality enabled which allows the user to click and drag to highlight text, you really don't want to be competing within this.
Instead, you want to define a "hot zone" area around the component which would allow you "highlight" the component in some and allow the user to drag the component via it.
For example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class DragMe {
public static void main(String[] args) {
new DragMe();
}
public DragMe() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JTextArea ta = new JTextArea(10, 20);
ta.setText("Bananas in pajamas");
JScrollPane sp = new JScrollPane(ta);
DragProxyPane proxy = new DragProxyPane(sp);
proxy.setSize(proxy.getPreferredSize());
proxy.setLocation(100 - proxy.getWidth() / 2, 100 - proxy.getHeight()/ 2);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
});
frame.add(proxy);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class DragProxyPane extends JPanel {
public static final int BUFFER_ZONE = 10;
private boolean mouseInHouse;
private JComponent component;
private List<HotZone> hotZones;
public DragProxyPane(JComponent comp) {
MouseAdapter ma = new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
mouseInHouse = true;
repaint();
}
#Override
public void mouseExited(MouseEvent e) {
mouseInHouse = false;
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
Cursor cursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
for (HotZone hz : hotZones) {
if (hz.getBounds(getSize()).contains(e.getPoint())) {
cursor = hz.getCursor();
break;
}
}
setCursor(cursor);
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
setOpaque(false);
setLayout(new BorderLayout());
add(comp);
setBorder(new EmptyBorder(BUFFER_ZONE, BUFFER_ZONE, BUFFER_ZONE, BUFFER_ZONE));
hotZones = new ArrayList<>(8);
// Top left, middle, right
hotZones.add(new HotZone(0f, 0f, Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR)));
hotZones.add(new HotZone(0.5f, 0f, Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)));
hotZones.add(new HotZone(1f, 0f, Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR)));
// Left, right
hotZones.add(new HotZone(0f, 0.5f, Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)));
hotZones.add(new HotZone(1f, 0.5f, Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)));
// Bottom left, middle, right
hotZones.add(new HotZone(0f, 1f, Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR)));
hotZones.add(new HotZone(0.5f, 1f, Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)));
hotZones.add(new HotZone(1f, 1f, Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR)));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (mouseInHouse) {
g2d.setColor(Color.BLACK);
for (HotZone hotZone : hotZones) {
g2d.draw(hotZone.getBounds(getSize()));
}
}
g2d.dispose();
}
public class HotZone {
private float x, y;
private Cursor cursor;
public HotZone(float x, float y, Cursor cursor) {
this.x = x;
this.y = y;
this.cursor = cursor;
}
public Cursor getCursor() {
return cursor;
}
public Rectangle getBounds(Dimension size) {
return getBounds(size.width - 1, size.height - 1);
}
public Rectangle getBounds(int width, int height) {
int halfBuffer = BUFFER_ZONE / 2;
float xPos = (width * x) - halfBuffer;
float yPos = (height * y) - halfBuffer;
xPos = Math.min(Math.max(0, xPos), width - BUFFER_ZONE);
yPos = Math.min(Math.max(0, yPos), height - BUFFER_ZONE);
return new Rectangle(Math.round(xPos), Math.round(yPos), BUFFER_ZONE, BUFFER_ZONE);
}
}
}
}
This sets up a simple proxy component which acts as the hot zone manager, detecting the mouse coming into or out of it and updating the cursor based on its location within in it, but it does not disrupt the normal operations of the component.
Now, this example doesn't drag, sorry, you have plenty of other examples which should be able to get you over the line, but, you could simply add a MouseListener/MouseMoitionListener to the proxy to detect when the user drags, but you will need to add some more functionality to it to determine what that drag actually means (resize or move) ;)
So I am working on a project here that requires a custom JLayeredPane - like class.
It has two members 'ground' and 'foreground' that are JPanel and an background (Image) member.
The way it was supposed to show was that the background Image should have been drawn and then all the components of the ground on top of it and then foreground's components at the apex. So foreground covers up ground which covers up background. Background should be shown only at places that do not have a Component in ground and foreground or where there is transparency in the JPanels.
It's paint function goes like this:
#Override
public void paint(Graphics g){
g.drawImage(background, 0, 0, null);
ground.paint(g.create());
foreground.paint(g.create());
g.dispose();
}
But nothing like that happens. Just the background image gets painted and nothing else shows.
I have used System.out.println() function to check that ground and foreground actually hold components and they do. But they just don't show.
Can anyone help me here?
The most significant issue is you're not calling super.paint, which is preventing what ever was previously painted to the Graphics context from been cleared or any child components from been painted.
For painting the background, you should be using paintComponent, which is used to paint the background of the component.
If you need to paint under the child components, but above the background, you should still use paintComponent, but paint the background first and then the next layer. The components will be painted after paintComponent.
Painting over components is actually more complex
Take a closer look at Custom Painting and Painting in Swing and AWT
Updated based on code snippets
In Screen which extends from Container, you are doing...
#Override
public void paint(Graphics g) {
super.paint(g);
GraphicsUtilities.drawPictureTiled(background, g);
paintComponents(g);
g.dispose();
}
Don't call paintComponents, super.paint has already done this.
Don't call dispose on a Graphics context you don't create
Based on the rest of the example code I have, you should be extending from JPanel and overriding paintComponent instead. This will allow you to put under the component layer
Because GroundPanel and ForeGroundPanel are both JPanels, there's no need to ever paint them yourself. In fact, you could simply use OverlayLayout or even a GridBagLayout and add them directly to the NestedScreen which is itself a container...
So, I stripped down you example code so I could get it working with the missing code as an example. I got a little more fancy and simply made a JPanel to act as the pause screen
This is all done by simply overlaying the components on top of each other using a GridBagLayout
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test1001 {
public static void main(String[] args) {
new Test1001();
}
public Test1001() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
try {
NestedScreen screen = new NestedScreen();
screen.setBackgroundLayer(ImageIO.read(getClass().getResource("/Sky.png")));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(screen);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException exp) {
exp.printStackTrace();
}
}
});
}
public interface GraphicsEngineComponents {
}
public class NestedScreen extends Screen implements GraphicsEngineComponents {
GroundPanel ground;
ForeGroundPanel foreground;
private PausePane pausePane;
public NestedScreen() {
ground = new GroundPanel();
foreground = new ForeGroundPanel();
pausePane = new PausePane();
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
add(pausePane, gbc);
add(foreground, gbc);
add(ground, gbc);
MouseAdapter handler = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
pausePane.setVisible(!pausePane.isVisible());
}
};
addMouseListener(handler);
foreground.addMouseListener(handler);
ground.addMouseListener(handler);
}
public GroundPanel getGroundLayer() {
return ground;
}
public ForeGroundPanel getForegroundLayer() {
return foreground;
}
public void setBackgroundLayer(BufferedImage background) {
super.setBackgroundLayer(background);
}
public class GroundPanel extends JPanel {
public GroundPanel() {
setOpaque(false);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(0, getHeight() - 200, getWidth(), 200);
}
}
public class PausePane extends JPanel {
private JLabel label;
public PausePane() {
setVisible(false);
setOpaque(false);
setBackground(new Color(0, 0, 0, 128));
setLayout(new GridBagLayout());
label = new JLabel("Paused");
label.setHorizontalAlignment(JLabel.CENTER);
label.setVerticalAlignment(JLabel.CENTER);
Font font = label.getFont();
font = font.deriveFont(Font.BOLD, 48f);
label.setFont(font);
label.setForeground(Color.WHITE);
add(label);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
}
}
public class ForeGroundPanel extends JPanel {
private BufferedImage pony;
public ForeGroundPanel() {
setOpaque(false);
try {
pony = ImageIO.read(getClass().getResource("/Pony.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (pony != null) {
int x = (getWidth() - pony.getWidth()) / 2;
int y = getHeight() - 200 - (pony.getHeight() / 2);
g.drawImage(pony, x, y, this);
}
}
}
}
public class Screen extends JPanel implements GraphicsEngineComponents {
private BufferedImage background;
public Screen() {
}
#Override
public String toString() {
return "Screen{" + "background=" + background + '}';
}
public BufferedImage getBackgroundPicture() {
return background;
}
#Override
public Dimension getPreferredSize() {
return background == null ? super.getPreferredSize() : new Dimension(background.getWidth(), background.getHeight());
}
protected void setBackgroundLayer(BufferedImage background) {
if (background != null && background.getHeight() != 0 && background.getWidth() != 0) {
this.background = background;
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
g.drawImage(background, 0, 0, this);
}
}
}
}
Take a look at Painting in AWT and Swing and Performing Custom Painting to understand how painting works in Swing.
A basic idea would be to avoid using all these compound or nested components and instead, create an engine that can paint the layers directly onto a Graphics context, maybe even painting to a BufferedImage which you can the paint onto a single component...
There are a few ways you go about doing this. I'll just introduce one way.
Create a background panel where you paint the background image (in the example below, it is BackgroundPanel with the image only being the forresty background). Set that panel as the content pane to the frame.
Create another ground panel where you can also paint something (in the example below if it the GroundPanel with only the image of bugs bunny painted.
Create your foreground panel and add it to the ground panel. You can add your foreground components to it. (in the example below the foreground image is the grassy hill, and I also add a button to it
All the panels' opaque property should be set to false, as to allow the panel behind it to be shown under any transparency.
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class ThreeTier {
public static final int DIM_WIDTH = 600;
public static final int DIM_HEIGHT = 400;
private BufferedImage backgroundImage;
private BufferedImage groundImage;
private BufferedImage foregroundImage;
public ThreeTier() {
initImages();
JFrame frame = new JFrame();
frame.setContentPane(new BackgroundPanel());
frame.add(new GroundPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void initImages() {
try {
backgroundImage = ImageIO.read(getClass().getResource("/resources/background.png"));
foregroundImage = ImageIO.read(getClass().getResource("/resources/foreground.png"));
groundImage = ImageIO.read(getClass().getResource("/resources/bugsBunny.png"));
} catch (IOException ex) {
Logger.getLogger(ThreeTier.class.getName()).log(Level.SEVERE, null, ex);
}
}
class BackgroundPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(backgroundImage, 0, 0, DIM_WIDTH, DIM_HEIGHT, this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(ThreeTier.DIM_WIDTH, ThreeTier.DIM_HEIGHT);
}
}
class GroundPanel extends JPanel {
private static final String RIGHT_ACTION = "rightAction";
private int imageX = 50;
private int imageY = 140;
public GroundPanel() {
setOpaque(false);
add(new ForegroundPanel());
InputMap im = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke("RIGHT"), RIGHT_ACTION);
getActionMap().put(RIGHT_ACTION, new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if (imageX >= DIM_WIDTH) {
imageX = 0 - groundImage.getWidth();
repaint();
} else {
imageX += 10;
repaint();
}
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(groundImage, imageX, imageY, groundImage.getWidth(), groundImage.getHeight(), this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(ThreeTier.DIM_WIDTH, ThreeTier.DIM_HEIGHT);
}
}
class ForegroundPanel extends JPanel {
public ForegroundPanel() {
setOpaque(false);
setLayout(new FlowLayout(FlowLayout.TRAILING, 10, 0));
JButton button = new JButton("I'm in the Foreground!");
add(button);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(foregroundImage, 0, 0, DIM_WIDTH, DIM_HEIGHT, this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(ThreeTier.DIM_WIDTH, ThreeTier.DIM_HEIGHT);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ThreeTier();
}
});
}
}
UPDATE
Of course you could always just use the JLayeredPane. That's what it's for. See this example
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
public class LayeredPaneDemo {
public static final int DIM_WIDTH = 600;
public static final int DIM_HEIGHT = 400;
public LayeredPaneDemo() {
ContainerPanel container = new ContainerPanel();
JLabel title = new JLabel("Lame Google Map");
title.setFont(new Font("verdana", Font.BOLD, 36));
title.setHorizontalAlignment(JLabel.CENTER);
JPanel panel = new JPanel(new GridBagLayout());
panel.add(container);
JFrame frame = new JFrame();
frame.add(panel);
frame.add(title, BorderLayout.NORTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new LayeredPaneDemo();
}
});
}
public class ContainerPanel extends JPanel {
public ContainerPanel() {
JLayeredPane layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(new Dimension(DIM_WIDTH, DIM_HEIGHT));
BackgroundPanel bg = new BackgroundPanel();
GroundPanel gg = new GroundPanel();
ForegroundPanel fg = new ForegroundPanel();
bg.setBounds(0, 0, DIM_WIDTH, DIM_HEIGHT);
layeredPane.add(bg, new Integer(1));
gg.setBounds(0, 0, DIM_WIDTH, DIM_HEIGHT);
layeredPane.add(gg, new Integer(2));
fg.setBounds(0, 0, DIM_WIDTH, DIM_HEIGHT);
layeredPane.add(fg, new Integer(3));
setLayout(new GridBagLayout());
add(layeredPane);
setBorder(new LineBorder(Color.BLUE, 10));
}
}
public class ForegroundPanel extends JPanel {
public ForegroundPanel() {
JPanel buttonPanel = new JPanel(new GridLayout(3, 3));
buttonPanel.setOpaque(false);
buttonPanel.add(new JLabel());
buttonPanel.add(new JButton("UP"));
buttonPanel.add(new JLabel());
buttonPanel.add(new JButton("Left"));
buttonPanel.add(new JLabel());
buttonPanel.add(new JButton("Right"));
buttonPanel.add(new JLabel());
buttonPanel.add(new JButton("Down"));
buttonPanel.add(new JLabel());
FlowLayout flow = (FlowLayout) getLayout();
flow.setAlignment(FlowLayout.TRAILING);
flow.setHgap(0);
flow.setVgap(0);
add(buttonPanel);
setOpaque(false);
}
}
public class GroundPanel extends JPanel {
Image image = null;
public GroundPanel() {
try {
image = ImageIO.read(getClass().getResource("/resources/california.png"));
} catch (IOException ex) {
Logger.getLogger(LayeredPaneDemo.class.getName()).log(Level.SEVERE, null, ex);
}
setOpaque(false);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, DIM_WIDTH, DIM_HEIGHT, this);
}
}
public class BackgroundPanel extends JPanel {
public BackgroundPanel() {
setLayout(new GridBagLayout());
setBackground(Color.WHITE);
try {
Image img = ImageIO.read(getClass().getResource("/resources/google.jpg"));
add(new JLabel(new ImageIcon(img)));
} catch (IOException ex) {
Logger.getLogger(LayeredPaneDemo.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
I have a program which should has splash screen on JPanel, after button click should show another JPanel (object of the class) and draw shapes. I tried remove splash JPanel and after that add JPanel for drawing but it doeesn't work. How can I fix it? Two JLabel should be in the center of screen and it should be on 2 lines.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JComponent;
/**
*
* #author Taras
*/
public class MyComponent extends JComponent {
int i;
Color randColor;
public MyComponent()
{
this.i = i;
addMouseListener(new MouseHandler());
}
private ArrayList<Rectangle2D> arrOfRect=new ArrayList<>();
private ArrayList<Ellipse2D> arrOfEllipse=new ArrayList<>();
// private ArrayList<Color> randColor = new ArrayList<>();
Random rand = new Random();
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (Rectangle2D r : arrOfRect) {
g.setColor(new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat()));
g2.draw(r);
}
for (Ellipse2D e : arrOfEllipse) {
g.setColor(new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat()));
g2.draw(e);
}
}
public void add(Point2D p)
{
double x=p.getX();
double y=p.getY();
if (Pole.i == 1){
Ellipse2D ellipse = new Ellipse2D.Double(x, y, 100,100);
//randColor = new Color(randRed(), randGreen(), randBlue());
arrOfEllipse.add(ellipse);
}
if (Pole.i == 2){
Rectangle2D rectangls=new Rectangle2D.Double(x, y, 100, 100);
arrOfRect.add(rectangls);
}
if (Pole.i == 3){
Rectangle2D rectangls=new Rectangle2D.Double(x, y, 150, 100);
arrOfRect.add(rectangls);
}
if (Pole.i == 4){
Ellipse2D ellipse = new Ellipse2D.Double(x, y, 100,50);
arrOfEllipse.add(ellipse);
}
}
private class MouseHandler extends MouseAdapter {
public void mousePressed(MouseEvent event)
{
add(event.getPoint());
//Color rColor = new Color(randRed(), randGreen(), randBlue());
//randColor.add(rColor);
repaint();
}
}
private int randRed() {
int red;
Random randomNumber = new Random();
red = randomNumber.nextInt(255);
return red;
}
private int randGreen() {
int green;
Random randomNumber = new Random();
green = randomNumber.nextInt(255);
return green;
}
private int randBlue() {
int blue;
Random randomNumber = new Random();
blue = randomNumber.nextInt(255);
return blue;
}
}
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
import org.omg.CosNaming.NameComponent;
public class Pole extends JFrame {
public static int i;
public static JPanel nameContainer = new JPanel(new GridLayout(2, 1));
public static JFrame frame= new JFrame("Shape Stamper!");
public static void main(String[] args) {
JPanel container;
JButton circle = new JButton("Circle");
JButton square = new JButton("Square");
JButton rectangle = new JButton("Rectangle");
JButton oval = new JButton("Oval");
JLabel programName = new JLabel("Shape Stamper!");
JLabel programmerName = new JLabel("Progrramed by: ");
Font font = new Font("Serif", Font.BOLD, 32);
programName.setFont(font);
font = new Font("Serif", Font.ITALIC, 16);
programmerName.setFont(font);
programName.setHorizontalAlignment(JLabel.CENTER);
programmerName.setHorizontalAlignment(JLabel.CENTER);
//programmerName.setVerticalAlignment(JLabel.CENTER);
// nameContainer.setLayout(new BorderLayout());
nameContainer.add(programName);
nameContainer.add(programmerName);
//nameContainer.setLayout(new BoxLayout(nameContainer, BoxLayout.X_AXIS));
container = new JPanel(new GridLayout(1, 4));
container.add(circle);
container.add(square);
container.add(rectangle);
container.add(oval);
circle.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
i = 1;
frame.remove(nameContainer);
frame.repaint();
System.out.println(i);
}
});
square.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
i = 2;
}
});
rectangle.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
i = 3;
}
});
oval.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
i = 4;
}
});
MyComponent shape = new MyComponent();
frame.setSize(500, 500);
frame.add(shape, BorderLayout.CENTER);
frame.add(container, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Here's an example of making a splash screen using an image.
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.*;
public class CircleSplashScreen {
public CircleSplashScreen() {
JFrame frame = new JFrame();
frame.getContentPane().add(new ImagePanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setUndecorated(true);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setBackground(new Color(0, 0, 0, 0));
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new CircleSplashScreen();
}
});
}
#SuppressWarnings("serial")
public class ImagePanel extends JPanel {
BufferedImage img;
public ImagePanel() {
setOpaque(false);
setLayout(new GridBagLayout());
try {
img = ImageIO.read(new URL("http://www.iconsdb.com/icons/preview/royal-blue/stackoverflow-4-xxl.png"));
} catch (IOException ex) {
Logger.getLogger(CircleSplashScreen.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
}
}
I have developed a swing form which validates entries as the focus is lost from JTextComponent
and if the entry is correct ,the background is painted green Otherwise it is painted red.
Here is the code :-
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.text.JTextComponent;
public class Form extends JFrame implements FocusListener{
JTextField fname,lname,phone,email,address;
BufferedImage img;
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable(){public void run(){new Form();}});
}
public Form()
{
super("Form with Validation Capability");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400,300);
setLayout(new GridLayout(5,3));
try {
img=ImageIO.read(new File("src/warning.png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
add(new JLabel("First Name :"));
add(fname=new JTextField(20));
add(new JLabel("Last Name :"));
add(lname=new JTextField(20));
add(new JLabel("Phone Number :"));
add(phone=new JTextField(10));
add(new JLabel("Email:"));
add(email=new JTextField(20));
add(new JLabel("Address :"));
add(address=new JTextField(20));
fname.addFocusListener(this);
lname.addFocusListener(this);
phone.addFocusListener(this);
email.addFocusListener(this);
address.addFocusListener(this);
setVisible(true);
}
public void focusGained(FocusEvent e)
{
((JTextComponent) e.getSource()).setBackground(Color.WHITE);
}
public void focusLost(FocusEvent e)
{
if(e.getSource().equals(fname))
{
validationForText(fname);
}
else if(e.getSource().equals(lname))
{
validationForText(lname);
}
else if(e.getSource().equals(email))
{
validationForEmail(email);
}
else if(e.getSource().equals(phone))
{
validationForNumber(phone);
}
else{
((JTextComponent) e.getSource()).setBackground(Color.GREEN);
}
}
public void validationForText(JTextComponent comp)
{
String temp=comp.getText();
if (temp.matches("^[A-Za-z]+$")) {
comp.setBackground(Color.GREEN);
}
else
comp.setBackground(Color.RED);
}
public void validationForNumber(JTextComponent comp)
{
String text=comp.getText();
if(text.matches("^[0-9]+$"))
comp.setBackground(Color.GREEN);
else
comp.setBackground(Color.RED);
}
public void validationForEmail(JTextComponent comp)
{
String text=comp.getText();
if(text.matches("[^#]+#([^.]+\\.)+[^.]+"))
comp.setBackground(Color.GREEN);
else
comp.setBackground(Color.RED);
}
}
Here is the output to my simple app :
Now I also want to draw a warning symbol (buffered image) at the lower left corner of incorrect field.Can anyone help me how to do this as i am not understanding where to paint the image.
(I would like to do it using JLayeredPane as I am learning its application,any code snippet will really help).
Why not simply add a JLabel (using an appropriate LayoutManager to position it) with the inbuilt Swing warning icon UIManager.getIcon("OptionPane.warningIcon")
like so:
JLabel label=new JLabel(UIManager.getIcon("OptionPane.warningIcon"));
see here for more.
UPDATE:
As per your comment I would rather use GlassPane (and add JLabel to glasspane) for this as opposed too JLayeredPane. See here for more on RootPanes
Some suggestions:
Dont extend JFrame unnecessarily
Dont call setSize on JFrame. Use a correct LayoutManager and/or override getPreferredSize() where necessary and replace setSize call with pack() just before setting JFrame visible.
Dont implement FocusListener on the class unless you want to share the functionality with other classes.
Also get into the habit of using FocusAdapter vs FocusListener this applies to a few with appended Listener i.e MouseListener can be replaced for MouseAdapter. This allows us to only override the methods we want. In this case listener is correct as we do something on both overridden methods, but as I said more about the habit
Also always call super.XXX implementation of overridden methods i.e focusGained(FocusEvent fe) unless you are ignoring it for a reason
Here is code with above fixes including glasspane to show warning icon when field is red:
And removes it when is corrected:
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
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.HashMap;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.text.JTextComponent;
/**
*
* #author David
*/
public class GlassValidationPane extends JComponent {
private static JTextField fname, lname, phone, email, address;
private static GlassValidationPane gvp = new GlassValidationPane();
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame("Form with Validation Capability");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//f.setResizable(false);
f.setLayout(new GridLayout(5, 3));
f.add(new JLabel("First Name :"));
f.add(fname = new JTextField(20));
f.add(new JLabel("Last Name :"));
f.add(lname = new JTextField(20));
f.add(new JLabel("Phone Number :"));
f.add(phone = new JTextField(10));
f.add(new JLabel("Email:"));
f.add(email = new JTextField(20));
f.add(new JLabel("Address :"));
f.add(address = new JTextField(20));
f.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent ce) {
super.componentResized(ce);
gvp.refreshLocations();
}
});
FocusAdapter fl = new FocusAdapter() {
#Override
public void focusGained(FocusEvent fe) {
super.focusGained(fe);
((JTextComponent) fe.getSource()).setBackground(Color.WHITE);
}
#Override
public void focusLost(FocusEvent fe) {
super.focusLost(fe);
if (fe.getSource().equals(fname)) {
validationForText(fname);
} else if (fe.getSource().equals(lname)) {
validationForText(lname);
} else if (fe.getSource().equals(email)) {
validationForEmail(email);
} else if (fe.getSource().equals(phone)) {
validationForNumber(phone);
} else {
gvp.removeWarningIcon(((Component) fe.getSource()));
((JTextComponent) fe.getSource()).setBackground(Color.GREEN);
}
}
};
fname.addFocusListener(fl);
lname.addFocusListener(fl);
phone.addFocusListener(fl);
email.addFocusListener(fl);
address.addFocusListener(fl);
f.setGlassPane(gvp);
f.pack();
f.setVisible(true);
gvp.setVisible(true);
}
public void validationForText(JTextComponent comp) {
String temp = comp.getText();
if (temp.matches("^[A-Za-z]+$")) {
setGreen(comp);
} else {
setRed(comp);
}
}
public void validationForNumber(JTextComponent comp) {
String text = comp.getText();
if (text.matches("^[0-9]+$")) {
setGreen(comp);
} else {
setRed(comp);
}
}
public void validationForEmail(JTextComponent comp) {
String text = comp.getText();
if (text.matches("[^#]+#([^.]+\\.)+[^.]+")) {
setGreen(comp);
} else {
setRed(comp);
}
}
private void setRed(JTextComponent comp) {
comp.setBackground(Color.RED);
gvp.showWarningIcon(comp);
}
private void setGreen(JTextComponent comp) {
comp.setBackground(Color.GREEN);
gvp.removeWarningIcon(comp);
}
});
}
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.getWidth() - 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());
add(label);
label.setVisible(true);
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.getWidth() - 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;
}
}