I'm trying to add a image to a java canvas.
I'm using the "ImageIO.read" to get the image source. The problem i'm facing is that i don't know how to display it on the canvas after reading the image location. Also later i will need to load a different image(e.g. after a button pressed) how can i do this. The update (canvas.update) method needs a "Graphics" parameter instead of an image.
Below you'll find my code simplified (i left out all code that's not relevant to the canvas issue.)
public class MainWindow {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
window = new MainWindow();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public MainWindow() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
Canvas csStatusImage = new Canvas();
csStatusImage.setBounds(393, 36, 200, 200);
frame.getContentPane().add(csStatusImage);
Image iMg;
try {
iMg = ImageIO.read(new File("Images/Error_status_1.png"));
csStatusImage.imageUpdate(iMg, 10, 2, 2, 9, 10);
csStatusImage.checkImage(iMg, (ImageObserver) this);
csStatusImage.createImage((ImageProducer) iMg);
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
First of all, you going to need some way to paint the image. To achieve this, you can override the paint method of the java.awt.Canvas class
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
Frame frame = new Frame("Testing");
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.add(new ImageCanvas());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public class ImageCanvas extends Canvas {
private BufferedImage img;
public ImageCanvas() {
try {
img = ImageIO.read(new File("Images/Error_status_1.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
}
#Override
public void paint(Graphics g) {
super.paint(g);
if (img != null) {
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g.drawImage(img, x, y, this);
}
}
}
}
I have to tell you, AWT is out-of-date by some 15+ years, replaced by Swing. You may find it hard to get additional support with this API. If you can, you'd better of using Swing or JavaFX
Related
So im making my own game in Java, yeah a weird thing. The problem is that ive made a method to return a BufferedImage with an image loaded in it:
public static BufferedImage getImage(String img) {
try {
image = ImageIO.read(Game.class.getResourceAsStream("./img/" + img));
} catch (IOException e) {
e.printStackTrace();
}
image.flush();
return image;
}
This method is returning the image for my icon with no problems.
frame.setIconImage(Game.getImage("icon.png"));
The problems is when i draw the image on the canvas:
g.drawImage(Game.getImage("aa.png"), 0, 0,Game.WIDTH, Game.HEIGHT,null);
That displays this:
And the actual image is:
Can someone help me out?
I should say it works on Windows but not on GNU/Linux
Taking your image, and placing in a subdirectory/package below this class (in the img package) worked just fine for me
import java.awt.Dimension;
import java.awt.EventQueue;
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;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MenuPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class Game {
public static BufferedImage getImage(String named) throws IOException {
return ImageIO.read(Game.class.getResource("img/" + named));
}
}
public class MenuPane extends JPanel {
private BufferedImage background;
public MenuPane() {
try {
background = Game.getImage("aa.jpg");
} catch (IOException ex) {
ex.printStackTrace();
}
}
#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);
g.drawImage(background, 0, 0, this);
}
}
}
What did I notice? aa is a jpg when I download, but is named as a png in your code, might not be an issue, but is a different.
Without a Runnable example it's near impossible to know what else to suggest
I finally found that it was a hardware issue. I returned home and tested it on a VM + on the same HDD. It works just fine, sorry for taking your time to answer.
I used JFrame to import and display an image, and used mousemotionlistener to detect the mouse clicks, and I want to be able to draw on top of the image. I want to be able to, if the user makes a click, make that pixel a certain color while preserving the rest of the image, however, I couldn't find out how to use Graphics to do so without deleting the rest of the image or opening a new window.
public class Simple extends JFrame{
static ImageIcon icon;
static JFrame myframe;
static JLabel mylabel;
static BufferedImage image = null;
public static void main(String[] args) {
try{
image = ImageIO.read(new File("mypic.png"));
}
catch (IOException e) {
e.printStackTrace();
}
icon=new ImageIcon(image);
myframe=new JFrame();
myframe.setSize(200,200);
myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mylabel=new JLabel();
mylabel.setIcon(icon);
myframe.getContentPane().add(mylabel);
myframe.pack();
Container container = myframe.getContentPane();
MouseMotionEvents3 mousemotion = new MouseMotionEvents3();
container.add(mousemotion);
myframe.setVisible(true);
while(1 == 1) {
if(mousemotion.signal == true) {
System.out.println("second message");
mousemotion.signal = false;
}
}
}
}
class MouseMotionEvents3 extends JPanel implements MouseListener,
MouseMotionListener {
public boolean signal;
public MouseMotionEvents3() {
addMouseListener(this);
addMouseMotionListener(this);
signal = false;
}
public void mouseClicked(MouseEvent me) {
// System.out.println("i hate you");
}
public void mouseEntered(MouseEvent me) {
}
public void mouseExited(MouseEvent me) {
}
public void mousePressed(MouseEvent me) {
signal = true;
System.out.println("message");
}
public void mouseReleased(MouseEvent me) {
}
public void mouseDragged(MouseEvent me) {
}
public void mouseMoved(MouseEvent me) {
}
}
I would highly recommend that you start by having a read through Performing Custom Painting and the 2D Graphics Trail, they will provide you with a starting point.
There are a number of ways you might achieve this, this example simply keeps track of the click points and draws dots over the top of the image
import java.awt.Color;
import java.awt.Dimension;
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 java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private List<Point> points;
private BufferedImage image;
public TestPane() {
points = new ArrayList<>(25);
try {
image = ImageIO.read(new File("/Users/shanewhitehead/Desktop/Screen Shot 2017-03-09 at 1.55.18 pm.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
points.add(e.getPoint());
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (image != null) {
g2d.drawImage(image, 0, 0, this);
}
g2d.setColor(Color.RED);
for (Point p : points) {
g2d.fillOval(p.x - 4, p.y - 4, 8, 8);
}
g2d.dispose();
}
}
}
This example draws the dots directly to the image itself...
import java.awt.Color;
import java.awt.Dimension;
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 java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage image;
public TestPane() {
try {
image = ImageIO.read(new File("/Users/shanewhitehead/Desktop/Screen Shot 2017-03-09 at 1.55.18 pm.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (image != null) {
Point p = e.getPoint();
Graphics2D g2d = image.createGraphics();
g2d.setColor(Color.RED);
g2d.fillOval(p.x - 4, p.y - 4, 8, 8);
g2d.dispose();
repaint();
}
}
});
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(image, 0, 0, this);
g2d.dispose();
}
}
}
In both cases, they simply make use of the Graphics2D API
The simplest method would be to have a list of points that represent the pixels you wish to colour. Then override the paint method for the label to first call super.paint (to display the image) and then paint the pixels that have been clicked.
List<Point> points = new ArrayList<>();
myLabel = new JLabel() {
#Override
public void paint(Graphics g) {
super.paint(g);
points.forEach(p -> g.fillRect(p.x, p.y, 1, 1));
}
};
In your mouse handling just add the current point to the list and repaint the label.
public void mouseClicked(MouseEvent me) {
points.add(me.getPoint());
myLabel.repaint();
}
There are more sophisticated methods that involve buffered images but this is likely good enough to get you started.
I figured it out, I can use the getGraphics() method of the JFrame to allow myself to draw on top of the image.
edit: Andrew Thompson is right, minimizing the window removes the changes.
I used JFrame to import and display an image, and used mousemotionlistener to detect the mouse clicks, and I want to be able to draw on top of the image. I want to be able to, if the user makes a click, make that pixel a certain color while preserving the rest of the image, however, I couldn't find out how to use Graphics to do so without deleting the rest of the image or opening a new window.
public class Simple extends JFrame{
static ImageIcon icon;
static JFrame myframe;
static JLabel mylabel;
static BufferedImage image = null;
public static void main(String[] args) {
try{
image = ImageIO.read(new File("mypic.png"));
}
catch (IOException e) {
e.printStackTrace();
}
icon=new ImageIcon(image);
myframe=new JFrame();
myframe.setSize(200,200);
myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mylabel=new JLabel();
mylabel.setIcon(icon);
myframe.getContentPane().add(mylabel);
myframe.pack();
Container container = myframe.getContentPane();
MouseMotionEvents3 mousemotion = new MouseMotionEvents3();
container.add(mousemotion);
myframe.setVisible(true);
while(1 == 1) {
if(mousemotion.signal == true) {
System.out.println("second message");
mousemotion.signal = false;
}
}
}
}
class MouseMotionEvents3 extends JPanel implements MouseListener,
MouseMotionListener {
public boolean signal;
public MouseMotionEvents3() {
addMouseListener(this);
addMouseMotionListener(this);
signal = false;
}
public void mouseClicked(MouseEvent me) {
// System.out.println("i hate you");
}
public void mouseEntered(MouseEvent me) {
}
public void mouseExited(MouseEvent me) {
}
public void mousePressed(MouseEvent me) {
signal = true;
System.out.println("message");
}
public void mouseReleased(MouseEvent me) {
}
public void mouseDragged(MouseEvent me) {
}
public void mouseMoved(MouseEvent me) {
}
}
I would highly recommend that you start by having a read through Performing Custom Painting and the 2D Graphics Trail, they will provide you with a starting point.
There are a number of ways you might achieve this, this example simply keeps track of the click points and draws dots over the top of the image
import java.awt.Color;
import java.awt.Dimension;
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 java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private List<Point> points;
private BufferedImage image;
public TestPane() {
points = new ArrayList<>(25);
try {
image = ImageIO.read(new File("/Users/shanewhitehead/Desktop/Screen Shot 2017-03-09 at 1.55.18 pm.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
points.add(e.getPoint());
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (image != null) {
g2d.drawImage(image, 0, 0, this);
}
g2d.setColor(Color.RED);
for (Point p : points) {
g2d.fillOval(p.x - 4, p.y - 4, 8, 8);
}
g2d.dispose();
}
}
}
This example draws the dots directly to the image itself...
import java.awt.Color;
import java.awt.Dimension;
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 java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage image;
public TestPane() {
try {
image = ImageIO.read(new File("/Users/shanewhitehead/Desktop/Screen Shot 2017-03-09 at 1.55.18 pm.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (image != null) {
Point p = e.getPoint();
Graphics2D g2d = image.createGraphics();
g2d.setColor(Color.RED);
g2d.fillOval(p.x - 4, p.y - 4, 8, 8);
g2d.dispose();
repaint();
}
}
});
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(image, 0, 0, this);
g2d.dispose();
}
}
}
In both cases, they simply make use of the Graphics2D API
The simplest method would be to have a list of points that represent the pixels you wish to colour. Then override the paint method for the label to first call super.paint (to display the image) and then paint the pixels that have been clicked.
List<Point> points = new ArrayList<>();
myLabel = new JLabel() {
#Override
public void paint(Graphics g) {
super.paint(g);
points.forEach(p -> g.fillRect(p.x, p.y, 1, 1));
}
};
In your mouse handling just add the current point to the list and repaint the label.
public void mouseClicked(MouseEvent me) {
points.add(me.getPoint());
myLabel.repaint();
}
There are more sophisticated methods that involve buffered images but this is likely good enough to get you started.
I figured it out, I can use the getGraphics() method of the JFrame to allow myself to draw on top of the image.
edit: Andrew Thompson is right, minimizing the window removes the changes.
I have a program that scales an image to the size of the screen. I currently have a component listener listening for a componentResized event, but this is not what I want. I would like the method to only be called one the user lift's there finger off their mouse, not as they are doing the resizing. This way, my image will not constantly be resizing to the user's specifications.
Thanks!
A solution is to supply a Swing Timer which is reset each time componentResized is called. This injects a small delay between the last resize event and the time you should perform the resize action.
import javax.swing.Timer;
//...
// Declare an instance variable...
private Timer resizeTimer;
//...
// Probably in you classes constructor
resizeTimer = new Timer(250, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// Actually perform the resizing of the image...
resizeBackgroundImage();
}
});
// Don't want a repeating event...
resizeTimer.setRepeats(false);
//...
public void componentResized(ComponentEvent evt) {
resizeTimre.restart();
}
This basically, sets it up so that it will require 250 milliseconds between resize events before an attempt is made to resize the image. You can play around with the value to suit your own needs.
Updated with runnable example
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
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.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 RescaleTest {
public static void main(String[] args) {
new RescaleTest();
}
public RescaleTest() {
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 master;
private Image scaled;
private Timer resizeTimer;
public TestPane() {
try {
master = ImageIO.read(new File("/path/to/your/image"));
scaled = master;
} catch (IOException exp) {
exp.printStackTrace();
}
resizeTimer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
resizeBackground();
}
});
resizeTimer.setRepeats(false);
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
resizeTimer.restart();
}
});
}
protected void resizeBackground() {
// This is not my preferred scaling process, I prefer to use
// a divide and conqure approach and do so in the background
// where possible, but this is beyond the scope of the question...
if (getWidth() < getHeight()) {
scaled = master.getScaledInstance(getWidth(), -1, Image.SCALE_SMOOTH);
} else {
scaled = master.getScaledInstance(-1, getHeight(), Image.SCALE_SMOOTH);
}
repaint();
}
#Override
public Dimension getPreferredSize() {
return master != null ? new Dimension(master.getWidth(), master.getHeight()) : new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (scaled != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - scaled.getWidth(this)) / 2;
int y = (getHeight() - scaled.getHeight(this)) / 2;
g2d.drawImage(scaled, x, y, this);
g2d.dispose();
}
}
}
}
nb: The scaling used in this example is not my preferred method and was done for demonstration purposes only. See The Perils of Image.getScaledInstance() for details and Scale the ImageIcon automatically to label size for an alterantive approach...
If you put Toolkit.getDefaultToolkit().setDynamicLayout(false); right inside of main it will disable the frame from updating dynamically as you increase/decrease it's size. The ui will only be updated after you stop resizing.
import MainMenu.GameManager;
import java.awt.*;
import java.io.IOException;
public class Main {
Main(){
}
public static void main(String[] args) throws IOException {
GameManager manager = new GameManager();
Toolkit.getDefaultToolkit().setDynamicLayout(false);
}
}
I've got an editor with lots of image thumbnails. I'd like a double-click on an image to display the full resolution image using a modal undecorated dialog. Ideally, this would be animated, to show the image zooming up to full resolution on the center of the screen, then any click would make the image go away, either zooming back out or fading away.
I'm not concerned with establishing an exact behavior, I just want something slick. I've found plenty of JavaScript examples for this, but is there anything built for Swing?
This piece of code does more or less the trick...
There is still a problem in the way I'm setting the dialog's location...
Hope it helps.
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class OpenImageZooming {
private static final int NB_STEPS = 30;
private static final long OPENING_TOTAL_DURATION = 3000;
public static void main(String[] args) {
OpenImageZooming me = new OpenImageZooming();
me.openImage(args[0]);
}
private JFrame frame;
private JDialog dialog;
private JPanelZooming panelZooming;
private void openImage(final String imagePath) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame = new JFrame();
frame.setTitle("Open image with zoom");
JPanel p = new JPanel(new BorderLayout());
p.add(new JLabel("click on button to display image"), BorderLayout.CENTER);
JButton button = new JButton("Display!");
frame.setContentPane(p);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Thread t = new Thread() {
#Override
public void run() {
displayImaggeWithProgressiveZoom(imagePath);
}
};
t.start();
}
});
p.add(button, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 100);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected void displayImaggeWithProgressiveZoom(String imagePath) {
try {
final BufferedImage image = ImageIO.read(new File(imagePath));
for (int i = 0; i < NB_STEPS; i++) {
displayDialog(i, NB_STEPS, image);
Thread.sleep(OPENING_TOTAL_DURATION / NB_STEPS);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void displayDialog(final int i, final int nbSteps, final BufferedImage image) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
if (dialog == null) {
dialog = new JDialog(frame);
dialog.setUndecorated(true);
dialog.setModal(false);
panelZooming = new JPanelZooming(image);
dialog.setContentPane(panelZooming);
dialog.setSize(0, 0);
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
}
int w = (i + 1) * image.getWidth() / nbSteps;
int h = (i + 1) * image.getHeight() / nbSteps;
panelZooming.setScale((double) (i + 1) / nbSteps);
dialog.setSize(w, h);
dialog.setLocationRelativeTo(null);
}
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#SuppressWarnings("serial")
public static class JPanelZooming extends JPanel {
private BufferedImage image;
private double scale = 1.0d;
public JPanelZooming(BufferedImage image) {
this.image = image;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
AffineTransform at = g2.getTransform();
AffineTransform oldTransform = (AffineTransform) at.clone();
at.scale(scale, scale);
g2.setTransform(at);
g2.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
g2.setTransform(oldTransform);
}
public void setScale(double scale) {
this.scale = scale;
}
}
}
You can create a custom control that displays the image at the scale you want.
1) Create a BufferedImage from the image file you want using ImageIO.read(file) (you can also create it from an InputStream)
2) Extend the JComponent or Canvas class and overload the paint function to draw the animated image using Graphics.DrawImage() and set the width and height based on how long the window has been open. Set a timer or use another thread to repeatedly have the component redraw itself for however long you want the animation to play.
I haven't done much with customized modal dialogs (I mostly find them annoying), but you can use a JDialog and and your component to it.