Unable Take screenshot of JFrame Java Swing - java

I have tried to save the JFrame as an image using the following approach.
try
{
BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
this.paint(image.getGraphics());
ImageIO.write(image,"png", new File("Test.png"));
}
catch(Exception exception)
{
//code
System.out.print("Exception unable to write image");
}
I am trying to save a screenshot as follows:
I would like to have even the title in my screenshot
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.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DividedSquare {
public static void main(String[] args) {
new DividedSquare();
}
public DividedSquare() {
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 TriangleShape baseTriangle;
private Color[] colors;
public TestPane() {
colors = new Color[]{Color.RED, Color.GREEN, Color.BLUE, Color.MAGENTA};
}
#Override
public void invalidate() {
super.invalidate();
baseTriangle = new TriangleShape(
new Point(0, 0),
new Point(getWidth(), 0),
new Point(getWidth() / 2, getHeight() / 2));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
String text[] = new String[]{
"123.123",
"456.789",
"012.315",
"678.921"
};
FontMetrics fm = g2d.getFontMetrics();
double angel = 0;
for (int index = 0; index < 4; index++) {
g2d.setColor(colors[index]);
Path2D rotated = rotate(baseTriangle, angel);
g2d.fill(rotated);
Rectangle bounds = rotated.getBounds();
int x = bounds.x + ((bounds.width - fm.stringWidth(text[0])) / 2);
int y = bounds.y + (((bounds.height - fm.getHeight()) / 2) + fm.getAscent());
g2d.setColor(Color.WHITE);
g2d.drawString(text[index], x, y);
angel += 90;
}
g2d.setColor(Color.BLACK);
g2d.drawLine(0, 0, getWidth(), getHeight());
g2d.drawLine(getWidth(), 0, 0, getHeight());
g2d.dispose();
try
{
BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
frame.paint(image.getGraphics());
ImageIO.write(image,"png", new File("Practice.png"));
}
catch(Exception exception)
{
//code
System.out.print("Exception to write image");
}
}
public Path2D rotate(TriangleShape shape, double angel) {
Rectangle bounds = shape.getBounds();
int x = bounds.width / 2;
int y = bounds.width / 2;
return new Path2D.Float(shape, AffineTransform.getRotateInstance(
Math.toRadians(angel),
x,
y));
}
}
public class TriangleShape extends Path2D.Double {
public TriangleShape(Point2D... points) {
moveTo(points[0].getX(), points[0].getY());
lineTo(points[1].getX(), points[1].getY());
lineTo(points[2].getX(), points[2].getY());
closePath();
}
}
}
But I the image does not get created. I am unable to understand why.
I looked at this but am unable to understand how to incorporate it in my case.
Edit
Based on comments, I tried using robot class but am unable to know where to call this function from. If I call this function from the paint() method, I am unable to get the colors and text.
void screenshot()
{
try
{
Robot robot = new Robot();
// Capture the screen shot of the area of the screen defined by the rectangle
Point p = frame.getLocationOnScreen();
System.out.print("point" + p);
BufferedImage bi=robot.createScreenCapture(new Rectangle((int)p.getX(),(int)p.getY(),frame.getWidth(),frame.getHeight()));
ImageIO.write(bi, "png", new File("imageTest.png"));
}
catch(Exception exception)
{
//code
System.out.print("Exception to write image");
}
}

There are at least two ways you might achieve this...
You Could...
Use Robot to capture a screen shot. For example
The problem with this is it takes a little effort to target the component you want to capture. It also only captures a rectangular area, so if the component is transparent, Robot won't respect this...
You Could...
Use printAll to render the component to your own Graphics context, typically from a BufferedImage
printAll allows you to print a component, because the intention is not to print this to the screen, printAll disables double buffering, making it more efficient to use when you don't want to render the component to the screen, such printing it to a printer...
Forexample

You can use Robot to capture screenshot. But it not gives Jframe Screenshot. We need to give correct coordinates and refer the frame. gFrame is my frame name and below code works for only Jframe area screenshot.
try {
Robot cap=new Robot();
Rectangle rec=new Rectangle(gFrame.getX(),gFrame.getY(),gFrame.getWidth(),gFrame.getHeight());
BufferedImage screenshot=cap.createScreenCapture(rec);
ImageIO.write(screenshot, "JPG",
new File("C:\\Users\\ruwan\\Downloads\\screenshot.jpg");
} catch (Exception e) {
e.printStackTrace();
}

Related

Java - Determining if two Ellipses intersect

I'm creating a 2D topdown shooter game with Java Swing in which I want circular hitboxes for my player and enemies as well as projectiles. For hit detection I need to figure out if there is an intersection between a projtile and a Sprite (player or enemy). My issue is that Ellipse2D's intersect function (that takes a position a width and height) creates a Rectangle out of the arguments. In its description it advises using Area for high precision and I was hoping it had an intersect function for any shape but that also casts its argument to a Rectangle.
Here's the jist of my Sprite object:
public class Sprite {
protected float worldX;
protected float worldY;
protected float drawX;
protected float drawY;
protected int width;
protected int height;
protected Image image;
...
}
In essence I'm storing their x and y coordinates as well as their width and height.(drawX and drawY are only used for rendering)
Is there a build-in method (preferably in Swing) to intersect Ellipses with other shapes (specifically other Ellipses and Rectangles) or is there no better option then implementing these by hand?
With a simple modification to the answer form Detecting collision of two sprites that can rotate
You can end up with something like...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Ellipse2D rect01;
private Rectangle rect02;
private int angle = 0;
public TestPane() {
rect01 = new Ellipse2D.Double(0, 0, 200, 50);
rect02 = new Rectangle(0, 0, 100, 100);
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
angle++;
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(250, 250);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth();
int height = getHeight();
AffineTransform at = new AffineTransform();
int center = width / 2;
int x = center + (center - rect01.getBounds().width) / 2;
int y = (height - rect01.getBounds().height) / 2;
at.translate(x, y);
at.rotate(Math.toRadians(angle), rect01.getBounds().width / 2, rect01.getBounds().height / 2);
GeneralPath path1 = new GeneralPath();
path1.append(rect01.getPathIterator(at), true);
g2d.fill(path1);
g2d.setColor(Color.BLUE);
g2d.draw(path1.getBounds());
at = new AffineTransform();
x = (center - rect02.width) / 2;
y = (height - rect02.height) / 2;
at.translate(x, y);
at.rotate(Math.toRadians(-angle), rect02.width / 2, rect02.height / 2);
GeneralPath path2 = new GeneralPath();
path2.append(rect02.getPathIterator(at), true);
g2d.fill(path2);
g2d.setColor(Color.BLUE);
g2d.draw(path2.getBounds());
Area a1 = new Area(path1);
Area a2 = new Area(path2);
a2.intersect(a1);
if (!a2.isEmpty()) {
g2d.setColor(Color.RED);
g2d.fill(a2);
}
g2d.dispose();
}
}
}

How to edit the pixels in a BufferedImage?

After scouring the internet for days, I found a Question that seemed to address my goal. (I'm trying to draw/edit an individual pixel in an image, and render it.) In said question, The ask-er requested code for a Black BufferedImage. The top Answer provided that code, and appears to work beautifully, until you try to change it to something other than black. Here's the Code:
package myProjectPackage;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.*;
public class Copypasta {
public static JFrame frame;
BufferedImage img;
public static int WIDTH = 500;
public static int HEIGHT = 500;
public Copypasta() {
}
public static void main(String[] a){
Copypasta t=new Copypasta();
frame = new JFrame("WINDOW");
frame.setVisible(true);
t.start();
frame.add(new JLabel(new ImageIcon(t.getImage())));
frame.pack();
// Better to DISPOSE than EXIT
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
public Image getImage() {
return img;
}
public void start(){
img = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
int[] pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
boolean running=true;
while(running){
BufferStrategy bs=frame.getBufferStrategy();
if(bs==null){
frame.createBufferStrategy(4);
return;
}
for (int i = 0; i < WIDTH * HEIGHT; i++)
pixels[i] = 0; //This is what i've been trying to change.
Graphics g= bs.getDrawGraphics();
g.drawImage(img, 0, 0, WIDTH, HEIGHT, null);
g.dispose();
bs.show();
}
}
}
I Apologize for the indentation errors. I promise it looks right in the editor.
When set to BufferedImage type ARGB, the black background disappears, causing me to believe that the start function isn't drawing to the Image at all, or the drawn image is not being drawn on the screen. Either way, There is something that I don't understand. If you have the time, I would appreciate some help Identifying What is going wrong, if not an explanation of why. Thank you all,
-Navi.
Link to Original Question: drawing your own buffered image on frame
Several things jump out, the use of BufferStrategy is probably overkill. Unless you absolutely must have control over the paint process, you really don't need it. Using a BufferStrategy also precludes the use of Swing based components which might or might not be an issue.
Trying to manipulate the pixel data directly is probably also a little overkill, instead you can use BufferedImage.setRGB(int, int, int), which allows you to set the color of the pixel at the specified x/y position, for example...
img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
img.setRGB(x, y, Color.RED.getRGB());
}
}
But, even this is a little overkill, the same thing can be achieved by using the provided 2D Graphics API...
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.dispose();
Which you will probably find is faster (not just from a coding point of view).
Take a look at:
Performing Custom Painting
Painting in AWT and Swing
2D Graphics
For more details...
Working example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestImage1 {
public static void main(String[] args) {
new TestImage1();
}
public TestImage1() {
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 img;
public TestPane() {
img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
//for (int x = 0; x < img.getWidth(); x++) {
// for (int y = 0; y < img.getHeight(); y++) {
// img.setRGB(x, y, Color.RED.getRGB());
// }
//}
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.dispose();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(img, 0, 0, this);
g2d.dispose();
}
}
}

Having trouble displaying graphics in Swing

I've been trying to visually simulate a traffic problem, but for some reason I get only blank output in my swing window. Instead of a constantly-moving picture with vehicles, I get only a grey screen.
My drawing class looks as follows:
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class RoadNetwork extends JPanel {
BufferedImage tempicon = ImageIO.read(getClass().getResource("Truck.png"));
BufferedImage truckicon = new BufferedImage(tempicon.getWidth(), tempicon.getHeight(), BufferedImage.TYPE_INT_ARGB);
public RoadNetwork() throws IOException {
repaint();
}
protected void paintComponent (Graphics g) {
super.paintComponent(g);
g.clearRect(0, 0, 600, 600); // insert window size parameters here
for (int i = 0; i < AMEC.vehiclecounter; i++) {
if (AMEC.vehicle[i].spawned == true && AMEC.vehicle[i].finished == false) { // if the truck is somewhere on the plant
g.drawImage(truckicon, AMEC.getcoord(i)[0], AMEC.getcoord(i)[1], this);
}
}
g.drawImage(truckicon, 100, 100, this);
}
}
The call to the class in my main function is done as follows:
RoadNetwork roadnetwork = new RoadNetwork();
roadnetwork.setVisible(true);
JFrame frame = new JFrame();
frame.add(roadnetwork);
frame.setSize(600, 600);
frame.setVisible(true);
Then, with every iteration of my simulation, I call
roadnetwork.repaint();
What am I missing?
BufferedImage tempicon = ImageIO.read(getClass().getResource("Truck.png"));
BufferedImage truckicon = new BufferedImage(tempicon.getWidth(), tempicon.getHeight(), BufferedImage.TYPE_INT_ARGB);
At the end of the 2nd code line, truckicon is still completely invisible (since it is a transparent image that we have drawn nothing to). Try instead.
BufferedImage truckicon = ImageIO.read(getClass().getResource("Truck.png"));
I hate not knowing why something works. But I remember going through the Graphics totorial and seeing them do this in the constructor where they seem to draw the second image
BufferedImage img = ImageIO.read(imageSrc);
int w = img.getWidth(null);
int h = img.getHeight(null);
BufferedImage bi = new
BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics g = bi.getGraphics();
g.drawImage(img, 0, 0, null);
Here's the fix I made. I wish I could give more explanation, but feel free to check out the tutorial I linked
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class RoadNetwork extends JPanel {
BufferedImage tempicon;
BufferedImage truckicon;
public RoadNetwork() throws IOException {
tempicon = ImageIO.read(getClass().getResource("resources/stack_reverse.png"));
int w = tempicon.getWidth(null);
int h = tempicon.getHeight(null);
truckicon = new
BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics g = truckicon.getGraphics();
g.drawImage(tempicon, 0, 0, null);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//g.clearRect(0, 0, 600, 600); // insert window size parameters here
// for (int i = 0; i < AMEC.vehiclecounter; i++) {
// if (AMEC.vehicle[i].spawned == true && AMEC.vehicle[i].finished ==
// false) { // if the truck is somewhere on the plant
// g.drawImage(truckicon, AMEC.getcoord(i)[0], AMEC.getcoord(i)[1],
// this);
// }
// }
g.drawImage(truckicon, 100, 100, this);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
try {
RoadNetwork roadnetwork = new RoadNetwork();
roadnetwork.setVisible(true);
JFrame frame = new JFrame();
frame.add(roadnetwork);
frame.setSize(600, 600);
frame.setVisible(true);
} catch (IOException es) {
es.printStackTrace();
}
}
});
}
}
Also, I was going to suggest #AndrewThompson's answer, but because I didn't know the reason you were using two BufferedImages, I didn't want to suggest it. You may have been trying to do what the tutorial was doing.

Java fade in and out of images

I am trying to learn how to fade in and out images into another image or from another image. So, if I have 2 images, and 1 is being displayed at the moment, I want to display another image in the background and fade the first image out into the 2nd image. OR, I want to set the focus on the new image and slowly fade it in over the 1st image, then stop displaying the 1st one.
I'm not sure how:
to set focus, if even needed.
I can fade in if I change the alpha to 0 and increment up and only draw one image, however I cannot get it to fade out either with any variation of this code. (i.e. commenting out one image to draw).
Edit: Really, all I'm worried about is being able to have 2 images and make the image currently being displayed slowly disappear into the 2nd image. How that is accomplished doesn't need to be with this.
Here is a code sample I'm messing with:
import java.awt.AlphaComposite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class FadeIn extends JPanel implements ActionListener {
private Image imagem;
private Image image2;
private Timer timer;
private float alpha = 1f;
public FadeIn() {
imagem = (new ImageIcon(getClass().getResource(
"/resources/1stImage.jpg"))).getImage();
image2 = (new ImageIcon(getClass().getResource(
"/resources/2ndImage.jpg"))).getImage();
timer = new Timer(20, this);
timer.start();
}
// here you define alpha 0f to 1f
public FadeIn(float alpha) {
imagem = (new ImageIcon(getClass().getResource(
"/resources/1stImage.jpg"))).getImage();
this.alpha = alpha;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(imagem, 0, 0, 400, 300, null);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
alpha));
g2d.drawImage(image2, 0, 0, 400, 300, null);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Fade out");
frame.add(new FadeIn());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(420, 330);
// frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
alpha += -0.01f;
if (alpha <= 0) {
alpha = 0;
timer.stop();
}
repaint();
}
}
Basically, what this does is use the same alpha value, fading in from 0-1 and then using the same alpha, going from 1-0, allowing the two images to cross fade over each other...
The magic basically, happens in the paintComponent, where the image coming in using the alpha value and the outgoing image uses 1f - alpha.
Switching between the two images is actually a the same process, expect the inImage is swapped for the outImage
The timing is little different. Instead of a straight move from 0-1 using a standard delta (ie 0.01 for example), this uses a time based algorithm.
That is, I use a timer which ticks every 40 milliseconds or so, it then does a calculation based on the amount of time the timer has being running and calculates the alpha value accordingly...
This allows you to change the amount of time the animation will take, but also provides a slightly better algorithm that takes into account the passive nature of Swings rendering engine...
import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class FadeImage {
public static void main(String[] args) {
new FadeImage();
}
public FadeImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
public static final long RUNNING_TIME = 2000;
private BufferedImage inImage;
private BufferedImage outImage;
private float alpha = 0f;
private long startTime = -1;
public TestPane() {
try {
inImage = ImageIO.read(new File("/path/to/inImage"));
outImage = ImageIO.read(new File("/path/to/outImage"));
} catch (IOException exp) {
exp.printStackTrace();
}
final Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (startTime < 0) {
startTime = System.currentTimeMillis();
} else {
long time = System.currentTimeMillis();
long duration = time - startTime;
if (duration >= RUNNING_TIME) {
startTime = -1;
((Timer) e.getSource()).stop();
alpha = 0f;
} else {
alpha = 1f - ((float) duration / (float) RUNNING_TIME);
}
repaint();
}
}
});
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
alpha = 0f;
BufferedImage tmp = inImage;
inImage = outImage;
outImage = tmp;
timer.start();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(
Math.max(inImage.getWidth(), outImage.getWidth()),
Math.max(inImage.getHeight(), outImage.getHeight()));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));
int x = (getWidth() - inImage.getWidth()) / 2;
int y = (getHeight() - inImage.getHeight()) / 2;
g2d.drawImage(inImage, x, y, this);
g2d.setComposite(AlphaComposite.SrcOver.derive(1f - alpha));
x = (getWidth() - outImage.getWidth()) / 2;
y = (getHeight() - outImage.getHeight()) / 2;
g2d.drawImage(outImage, x, y, this);
g2d.dispose();
}
}
}
This is a easy and short most developers using java code for image fade.
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
/**
*
* #author ADMIN
*/
public class ImageFade extends JFrame {
ImageFade() {
setLayout(null);
JLabel l = new JLabel();
l.setBounds(0, 0, 100, 96);
add(l);
Thread tp = new Thread() {
#Override
public void run() {
for (int amp = 0; amp <= 500; amp++) {
try {
sleep(1);
try {
BufferedImage bim = ImageIO.read(new File("src/image/fade/image.png"));
BufferedImage nbim = new BufferedImage(bim.getWidth(), bim.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D createGraphics = nbim.createGraphics();
createGraphics.drawImage(bim, null, 0, 0);
RescaleOp r = new RescaleOp(new float[]{1f, 1f, 1f, (float) amp / 500}, new float[]{0, 0, 0, 0}, null);
BufferedImage filter = r.filter(nbim, null);
l.setIcon(new ImageIcon(filter));
} catch (Exception ex) {
System.err.println(ex);
}
} catch (InterruptedException ex) {
}
}
}
};
tp.start();
setUndecorated(true);
setBackground(new Color(0, 0, 0, 0));
setSize(100, 96);
setVisible(true);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
setAlwaysOnTop(true);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
ImageFade fr = new ImageFade();
}
}
in this code you can see a thread code. in the thread this image will fade in.
the used image is stack overflow web page's logo image.
only by shown code the image will fade in.
Thread tp = new Thread() {
#Override
public void run() {
for (int amp = 0; amp <= 500; amp++) {
try {
sleep(1);
try {
BufferedImage bim = ImageIO.read(new File("src/image/fade/image.png"));
BufferedImage nbim = new BufferedImage(bim.getWidth(), bim.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D createGraphics = nbim.createGraphics();
createGraphics.drawImage(bim, null, 0, 0);
RescaleOp r = new RescaleOp(new float[]{1f, 1f, 1f, (float) amp / 500}, new float[]{0, 0, 0, 0}, null);
BufferedImage filter = r.filter(nbim, null);
l.setIcon(new ImageIcon(filter));
} catch (Exception ex) {
System.err.println(ex);
}
} catch (InterruptedException ex) {
}
}
}
};
tp.start();
This code is very simple to use.
This is not from any book, internet or etc. It is developed by me.
A normal image is not able to change alpha. By code : BufferedImage nbim = new BufferedImage(bim.getWidth(), bim.getHeight(), BufferedImage.TYPE_INT_ARGB); the image will convert to ARGB - Alpha, Red, Green, Blue (R,G,B,A) image.
So you can change the alpha of a image.

Java ImageIcons and actioin listeners

I am creating a simple game where a person clicks on an image the score increases by one.
It seems simple enough, right? Here's the catch-- the images will be hidden partially behind other images!
Currently, I'm using several imageIcons to set up my scene. For instance, my foreground has an image "foreground.png," my background is "background.png", and my image that is hiding between the two is "hiding.png".
My first thought was to simply get the coordinates of the imageIcon hiding, add the height() and width() to them, and create a mouse listener that would only work in that specified region. However, that would give me a rectangle for the user to click which would defeat the purpose of hiding the object (someone could click the rigid boundary of the graphic behind the foreground).
Do you have any suggestions on how to make a mouse action listener work only on the VISIBLE pixels of an imageIcon? Yes, I understand that action listeners can only be applied to components (such as buttons) but "the button" just doesn't do what I want for this project.
Example 1
This basically uses a series of JLabels on a JLayeredPane. Each label has it's own mouse listener and when you mouse over it, will turn red. But, if there is a label above it, it won't respond to mouse events...
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ClickMyImages {
public static void main(String[] args) {
new ClickMyImages();
}
public ClickMyImages() {
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 JLayeredPane {
public TestPane() {
try {
BufferedImage img1 = ImageIO.read("/Image1");
BufferedImage img2 = ImageIO.read("/Image2");
BufferedImage img3 = ImageIO.read("/Image3");
BufferedImage img4 = ImageIO.read("/Image4");
BufferedImage img5 = ImageIO.read("/Image5");
JLabel label1 = new ClickableLabel(new ImageIcon(img1));
JLabel label2 = new ClickableLabel(new ImageIcon(img2));
JLabel label3 = new ClickableLabel(new ImageIcon(img3));
JLabel label4 = new ClickableLabel(new ImageIcon(img4));
JLabel label5 = new ClickableLabel(new ImageIcon(img5));
Dimension masterSize = getPreferredSize();
Dimension size = label1.getPreferredSize();
label1.setBounds((masterSize.width - size.width) / 2, (masterSize.height - size.height) / 2, size.width, size.height);
Point masterPoint = label1.getLocation();
size = label2.getPreferredSize();
label2.setBounds(
masterPoint.x - (size.width / 2),
masterPoint.y - (size.height / 2),
size.width, size.height);
size = label3.getPreferredSize();
label3.setBounds(
masterPoint.x + (size.width / 2),
masterPoint.y - (size.height / 2),
size.width, size.height);
size = label4.getPreferredSize();
label4.setBounds(
masterPoint.x - (size.width / 2),
masterPoint.y + (size.height / 2),
size.width, size.height);
size = label5.getPreferredSize();
label5.setBounds(
masterPoint.x + (size.width / 2),
masterPoint.y + (size.height / 2),
size.width, size.height);
add(label1);
add(label2);
add(label3);
add(label4);
add(label5);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 800);
}
}
// This is for demonstration purposes only!
public class ClickableLabel extends JLabel {
private boolean isIn = false;
public ClickableLabel(Icon image) {
super(image);
addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
isIn = true;
repaint();
}
#Override
public void mouseExited(MouseEvent e) {
isIn = false;
repaint();
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (isIn) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
}
}
}
}
Example 2
This examples uses the paintComponent method to renderer the images. It checks the pixel alpha of the image at the mouse point to determine if the mouse event should fall through or not.
I've been a little strict using an alpha value of 255, but you could soften it a little based on your needs (something like 225 instead for example)...
I've hard coded the layers so that the tree is always above the squirrel, but it wouldn't be hard to add all the images to List in the order you want them to appear and simple run down the list till you get a hit.
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ClickMyDrawnImages {
public static void main(String[] args) {
new ClickMyDrawnImages();
}
public ClickMyDrawnImages() {
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 tree;
private BufferedImage squirrel;
private BufferedImage mouseOver;
public TestPane() {
try {
tree = ImageIO.read(new File("Tree.png"));
squirrel = ImageIO.read(new File("Squirrel.png"));
} catch (IOException exp) {
exp.printStackTrace();
}
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
if (withinTree(e.getPoint())) {
mouseOver = tree;
} else if (withinSquirrel(e.getPoint())) {
mouseOver = squirrel;
} else {
mouseOver = null;
}
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected boolean withinTree(Point p) {
return withinBounds(p, getTreeBounds(), tree);
}
protected boolean withinSquirrel(Point p) {
return !withinBounds(p, getTreeBounds(), tree) && withinBounds(p, getSquirrelBounds(), squirrel);
}
protected Rectangle getTreeBounds() {
int width = getWidth();
int height = getHeight();
int x = (width - tree.getWidth()) / 2;
int y = (height - tree.getHeight()) / 2;
return new Rectangle(x, y, tree.getWidth(), tree.getHeight());
}
protected Rectangle getSquirrelBounds() {
Rectangle bounds = getTreeBounds();
return new Rectangle(
bounds.x - (squirrel.getWidth() / 4),
(getHeight() - squirrel.getHeight()) / 2,
squirrel.getWidth(), squirrel.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth();
int height = getHeight();
int x = (width - tree.getWidth()) / 2;
int y = (height - tree.getHeight()) / 2;
g.drawImage(highlight(squirrel), x - (squirrel.getWidth() / 4), (height - squirrel.getHeight()) / 2, this);
g2d.drawImage(highlight(tree), x, y, this);
g2d.dispose();
}
protected BufferedImage highlight(BufferedImage img) {
BufferedImage highlight = img;
if (img.equals(mouseOver)) {
highlight = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = highlight.createGraphics();
g2d.setColor(Color.RED);
g2d.drawImage(img, 0, 0, this);
g2d.setComposite(AlphaComposite.SrcAtop.derive(0.5f));
g2d.fillRect(0, 0, highlight.getWidth(), highlight.getHeight());
g2d.dispose();
}
return highlight;
}
protected boolean withinBounds(Point p, Rectangle bounds, BufferedImage image) {
boolean withinBounds = false;
if (bounds.contains(p)) {
int x = p.x - bounds.x;
int y = p.y - bounds.y;
int pixel = image.getRGB(x, y);
int a = (pixel >> 24) & 0xFF;
// could use a little weighting, so translucent pixels can be effected
if (a == 255) {
withinBounds = true;
}
}
return withinBounds;
}
}
}

Categories