Best manner to place 'markers' on an ImageIcon Java Swing? - java

I have a Java swing application where I've created an ImageIcon with a picture and displayed it to a screen. I did that by loading a URL as an ImageIcon and placing it in the Java Swing window as a label.
Now I need to place 'markers' on the image with other images.
In context: Place a picture of an eye on someones face over their eye.
I'd appreciate anyone who can point my in the right direction or give me some SSCCE code to work from.
What is the best manner to place 'markers' on an ImageIcon Java Swing?

The basic concept is, you need a temporary image onto which you can paint the master/base image and the marker.
Create a new BufferedImage. This would typically be the same size as the master image, but doesn't have to be.
Paint the master image onto BufferedImage
Paint the marker onto the BufferedImage
Create a new ImageIcon using the BufferedImage
Apply the ImageIcon to the label...
public class PaintIcon {
public static void main(String[] args) {
new PaintIcon();
}
public PaintIcon() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new PaintPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PaintPane extends JPanel {
private JLabel label;
private int state = 0;
private BufferedImage disk;
private BufferedImage play;
private BufferedImage pause;
private BufferedImage stop;
public PaintPane() {
setLayout(new GridBagLayout());
add((label = new JLabel()));
try {
disk = ImageIO.read(getClass().getResource("/cd.png"));
play = ImageIO.read(getClass().getResource("/media_play.png"));
pause = ImageIO.read(getClass().getResource("/media_pause.png"));
stop = ImageIO.read(getClass().getResource("/media_stop.png"));
} catch (Exception e) {
e.printStackTrace();
}
updateState();
label.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
state++;
if (state > 2) {
state = 0;
}
updateState();
}
});
}
protected void updateState() {
BufferedImage base = new BufferedImage(disk.getWidth(), disk.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = base.createGraphics();
g2d.drawImage(disk, 0, 0, this);
BufferedImage marker = null;
switch (state) {
case 0:
marker = stop;
break;
case 1:
marker = play;
break;
case 2:
marker = pause;
break;
}
int x = disk.getWidth() - marker.getWidth();
int y = disk.getHeight() - marker.getHeight();
g2d.drawImage(marker, x, y, this);
g2d.dispose();
label.setIcon(new ImageIcon(base));
}
}
}

Related

switching images dynamically on jframe

I have an assignment to create a GUI that switches images when a menu item is selected (ex. file, new picture) and also contains buttons for zooming in and out on the images. When I try switching images with my code, the image only partly loads. When I minimize the window and then reopen it, the image is fully loaded. I'm wondering why this is happening.
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
public class ImageZoom extends JPanel {
private Image image;
int x, y;
private JButton zoomIn;
private JButton zoomOut;
private JMenuBar bar;
private JMenu file;
private JMenuItem choosePic = new JMenuItem("New Picture");
private String pics[] = {"waterfall.jpg", "mountains.jpg"};
private int picIndex = 1;
int imageHeight = getHeight();
int imageWidth = getWidth();
int zoom = 1;
Image images[] = new Image[2];
public ImageZoom() {
try {
images[0] = ImageIO.read(new File("waterfall.jpg"));
images[1] = ImageIO.read(new File("mountains.jpg"));
} catch (IOException e) {}
zoomIn = new JButton("+");
zoomOut = new JButton("-");
JPanel panel = new JPanel();
bar = new JMenuBar();
file = new JMenu("File");
file.add(choosePic);
bar.add(file);
choosePic.addActionListener (new ActionListener() {
public void actionPerformed (ActionEvent e) {
if (e.getSource() == choosePic) {
repaint();
}
}
});
zoomIn.addActionListener (new ActionListener() {
public void actionPerformed (ActionEvent e) {
if (e.getSource() == zoomIn) {
if (zoom < 6) {
zoom += 1;
repaint();
}
}
}
});
zoomOut.addActionListener( new ActionListener() {
public void actionPerformed (ActionEvent e) {
if (e.getSource() == zoomOut) {
if (zoom > 1) {
zoom -= 1;
repaint();
}
}
}
});
}
public JPanel getButtonPanel () {
JPanel panel = new JPanel();
panel.add(zoomIn);
panel.add(zoomOut);
return panel;
}
public Image getImage() {
try {
image = ImageIO.read(new File(pics[picIndex % 2]));
picIndex++;
}
catch (IOException e){}
return image;
}
protected void paintComponent (Graphics g) {
imageHeight = getHeight() * zoom;
imageWidth = getWidth() * zoom;
super.paintComponent(g);
g.drawImage(getImage(), 0, 0, imageWidth, imageHeight, null);
}
public void createJFrame () {
JFrame frame = new JFrame();
ImageZoom imgZoom = new ImageZoom();
frame.setJMenuBar(bar);
frame.add(imgZoom);
frame.add(getButtonPanel(), BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(650, 650);
frame.setResizable(false);
frame.setVisible(true);
}
}
class Test {
public static void main (String[] args) {
ImageZoom zoom = new ImageZoom();
zoom.createJFrame();
}
}
For simplicity, you should just be using a JLabel and calling its setIcon method to switch the images. You could dynamically scale the images as required (just maintain a reference to the original)
Problem #1
You should be passing this to drawImage, this will allow the component to act as the ImageObserver and schedule additional reprints as required based on events from the image's state, which leads to
Problem #2
You should not be calling getImage from within the paintComponent method, paintComponent could be called for any number of reasons, many of which you don't control or even know about and paintComponent should simply paint the current state of the component and never, ever try and change the state
Side Note: Instead of repeatedly trying to load the images, it would be better to load them once and continue to reuse the loaded reference

Scaling an image quickly, and making sure it actually scales

I am trying to scale a screenshot taken by:
robot.createScreenCapture(SCREEN_RECT);
Im trying to get it down to an image that is 600X400 and fits into a JFrame that is 600X400
My program is using a swing worker to create an video out of each picture, or frames. The frames have a delay of 200ms per each. the image when told to rescale just shows the original image at the original dimensions. Does anyone know how to fix this, or should I just give up on the resize-ing?
#SuppressWarnings("serial")
public class temporaryShit extends JPanel
{
private static final int width = 600;
private static final int height = 400;
private JLabel displayedLabel = new JLabel();
public temporaryShit()
{
setLayout(new BorderLayout());
add(displayedLabel);
try {
MySwingWorker mySwingWorker = new MySwingWorker();
mySwingWorker.execute();
} catch (AWTException e) {
}
}
public void setLabelIcon(Icon icon) {
displayedLabel.setIcon(icon);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
private class MySwingWorker extends SwingWorker<Void, Icon>
{
private final Rectangle SCREEN_RECT = new Rectangle(0, 0, width, height);
private long delay = 200;
private Robot robot = null;
public MySwingWorker() throws AWTException
{
robot = new Robot();
}
#Override
protected Void doInBackground() throws Exception
{
Timer utilTimer = new Timer();
TimerTask task = new TimerTask()
{
#Override
public void run()
{
BufferedImage capturedImage = captureScreen();
publish(new ImageIcon(capturedImage));
}
};
utilTimer.scheduleAtFixedRate(task, delay, delay);
return null;
}
#Override
protected void process(List<Icon> chunks)
{
for (Icon icon : chunks)
{
setLabelIcon(icon);
}
}
private BufferedImage captureScreen()
{
BufferedImage img = robot.createScreenCapture(SCREEN_RECT);
return createResizedImage(img, width, height);
}
public BufferedImage createResizedImage(Image original, int width, int height)
{
BufferedImage scaledBI = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = scaledBI.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(original, 0, 0, width, height, null);
g.dispose();
return scaledBI;
}
}
private static void createAndShowGui()
{
temporaryShit mainPanel = new temporaryShit();
JFrame frame = new JFrame("SwingWorker Eg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGui();
}
});
}
}
You already have a new image with specified size - scaled, which you can use for rendering.
Here is a simple example:
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
class TestBrightness {
public static void main(String args[]) {
try {
URL imageUrl = new URL(
"http://duke.kenai.com/comfyChair/ComfyChairRadSmall.jpg");
BufferedImage ioImage = ImageIO.read(imageUrl);
JPanel panel = new JPanel();
Image scaledImg = ioImage.getScaledInstance(ioImage.getWidth() / 2,
ioImage.getHeight() / 2, Image.SCALE_SMOOTH);
panel.add(new JLabel(new ImageIcon(ioImage)));
panel.add(new JLabel(new ImageIcon(scaledImg)));
JOptionPane.showMessageDialog(null, panel, "100% vs 50%",
JOptionPane.INFORMATION_MESSAGE);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage(), "Failure",
JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
}
}
}
As a side note, there are many ways to scale an image and Image.getScaledInstance() may not be the best. You may be interested to take a look at The Perils of Image.getScaledInstance() for some details on Image.getScaledInstance()
EDIT: question update
Last question update removed all the details regarding getScaledInstance and invalidated this answer. getScaledInstance is a very slow method and it is also asynchronous. Try this method to get a resized image:
public static BufferedImage createResizedImage(Image original, int width,
int height) {
BufferedImage scaledBI = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = scaledBI.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(original, 0, 0, width, height, null);
g.dispose();
return scaledBI;
}
You may want to change rendering hints for better quality.
For a nicer and more complete image scaler take a look at getFasterScaledInstance() from Filthy Rich Clients book.
EDIT : last question update with posted code and SwingWorker
The implementation of SwingWorker is not correct. doInBackground() schedules java.Utils.Timer. This timer handles all updates, while the actual SwingWorker worker thread ends. All updates from the timer are fired not on Event Dispatch Thread. It may not be safe to allocate ImageIcon not on EDT. And for sure it is not safe to update UI, ie calling setLabelIcon() not on EDT. See Concurrency in Swing tutorial for details.
You can add while loop and Thread.sleep in doInBackground() and remove the timer. Alternatively, Swing timer may be more suitable for this case. Here is an example:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
public class DemoRobotPanel extends JPanel{
private static final long serialVersionUID = 1L;
private Image image;
private Robot robot;
private Rectangle CAPTURE_RECT;
private int TIMER_DELAY = 1000;
private int desiredWidth = 600;
private int desiredHeight = 400;
public DemoRobotPanel() {
CAPTURE_RECT = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
try {
robot = new Robot();
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
try {
BufferedImage img = robot.createScreenCapture(CAPTURE_RECT);
setImage(img);
} catch (HeadlessException e) {
e.printStackTrace();
}
}
};
Timer timer = new Timer(TIMER_DELAY, taskPerformer);
timer.start();
} catch (AWTException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(desiredWidth, desiredHeight);
}
public void setImage(Image image) {
this.image = image;
repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null)
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
}
private static void createAndShowGui() {
final DemoRobotPanel panel = new DemoRobotPanel();
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Try this:
public BufferedImage resize(BufferedImage bufferedImage, int resizeWidth, int resizeHeight) {
// Create new (blank) image of required (scaled) size
BufferedImage scaledImage = new BufferedImage(resizeWidth, resizeHeight, BufferedImage.TYPE_INT_ARGB);
// Paint scaled version of image to new image
Graphics2D graphics2D = scaledImage.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.drawImage(bufferedImage, 0, 0, resizeWidth, resizeHeight, null);
graphics2D.dispose();
return scaledImage;
}
You may want to try different RenderingHints.

putting marks on ImageIcon in JLabel

So I'm trying to find a way to modify an image in Java. In other words, if user clicks on the image, a mark will be put at the point where the user just clicked.
I have an ImageIcon which I put in a JLabel.
So far, the approach I took was to use JLayeredPanel to put another JPanel on top of the JLabel and draw on this JPanel:
//...
ImageIcon icon = new ImageIcon("foo.jpg");
JLabel lb = new JLabel(icon);
JPanel glass = new JPanel();
lb.setBounds(0, 0, 100, 100);
glass.setBounds(0, 0, 100, 100);
glass.setOpaque(false);
LayeredPane container = new LayeredPane();
container.add(lb, 1);
container.add(glass, 2);
//...
But this way doesn't seem to work. I never see the background image (the image in lb).
So I was wondering if I'm even on the right track at all? Or is there a cleaner way to achieve this?
There's nothing wrong with using a JLayeredPane or the glass pane for something like this, personally, I find it troublesome, because in a large application, you tend to want to use these layers for any number of things, so it becomes very complicated very fast.
I prefer to keep it "in the family" so to speak...
Personally, I would use a custom component. This isolates the work flow to a very particular location and makes it easier to provide the customisations that you might like...
public class MarkImage {
public static void main(String[] args) {
new MarkImage();
}
public MarkImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage background;
private List<Point> clickPoints;
public TestPane() {
clickPoints = new ArrayList<>(25);
try {
background = ImageIO.read(getClass().getResource("/Miho_Small.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
clickPoints.add(e.getPoint());
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return background == null ? super.getPreferredSize() : new Dimension(background.getWidth(), background.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g.drawImage(background, x, y, this);
}
g.setColor(Color.RED);
for (Point p : clickPoints) {
g.fillOval(p.x - 4, p.y - 4, 8, 8);
}
}
}
}
I'd also consider using JXLayer (AKA JLayer in Java 7). This is best described as a glass pane for components (on steroids). Check out How to decorate components for more details...
Updated with JLayer Example
This is an example using Java 7's JLayer. There are some slight differences between JLayer and JXLayer, but it wouldn't take much to convert it...
(Sorry, couldn't resist the temptation of having ago)
public class MarkLayer {
public static void main(String[] args) {
new MarkLayer();
}
public MarkLayer() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
try {
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
JLabel label = new JLabel(new ImageIcon(ImageIO.read(getClass().getResource("/Miho_Small.png"))));
LayerUI<JLabel> layerUI = new MarkLayerUI();
JLayer<JLabel> layer = new JLayer<>(label, layerUI);
frame.add(layer);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (Exception exp) {
exp.printStackTrace();
}
}
});
}
public class MarkLayerUI extends LayerUI<JLabel> {
private Map<JLayer, List<Point>> mapPoints;
public MarkLayerUI() {
mapPoints = new WeakHashMap<>(25);
}
#Override
public void installUI(JComponent c) {
System.out.println("install");
super.installUI(c);
JLayer layer = (JLayer) c;
layer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK);
}
#Override
public void uninstallUI(JComponent c) {
super.uninstallUI(c);
mapPoints.remove((JLayer) c);
}
#Override
protected void processMouseEvent(MouseEvent e, JLayer<? extends JLabel> l) {
if (e.getID() == MouseEvent.MOUSE_CLICKED) {
List<Point> points = mapPoints.get(l);
if (points == null) {
points = new ArrayList<>(25);
mapPoints.put(l, points);
}
Point p = e.getPoint();
p = SwingUtilities.convertPoint(e.getComponent(), p, l);
points.add(p);
l.repaint();
}
}
#Override
public void paint(Graphics g, JComponent c) {
Graphics2D g2d = (Graphics2D) g.create();
super.paint(g2d, c);
g2d.setColor(Color.BLUE);
g2d.drawRect(0, 0, c.getWidth() - 1, c.getHeight() - 1);
List<Point> points = mapPoints.get((JLayer) c);
if (points != null && points.size() > 0) {
g2d.setColor(Color.RED);
for (Point p : points) {
g2d.fillOval(p.x - 4, p.y - 4, 8, 8);
}
}
g2d.dispose();
}
}
}
The blue border is renderer as part of the layer, this gives you a guide as to where you can click - I did this for testing and demonstration purposes
You're on the right track with wanting to use another pane. In Java, there actually already is a glass pane that is designed for just this purpose. Read through this tutorial http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html and it should help you understand.

Add an Background image to a Panel

I have a JPanel, and i want to add an image as its background. How can i do that ?
frame = new JFrame("Some frame");
panel1 = new JPanel();
panel1.setBorder(new EmptyBorder(5, 5, 5, 5));
// NEED TO ADD AN IMAGE TO THIS PANEL
panel1.setLayout(cardlayout);
frame.getContentPane().add(panel1);
frame.setLocationByPlatform(true);
frame.setVisible(true);
I need to add an image to the panel and how can i do it ?
UPDATE 1
panel1 = new JPanel()
{
private static final long serialVersionUID = 1L;
#Override
public void paintComponent(Graphics g)
{
g.drawImage(Toolkit.getDefaultToolkit().createImage("1.jpg"), 0, 0, null);
}
};
You need to override the method paintComponent(Graphics g) of JPanel and use drawImage() on the Graphics object g as in this example.
Also, check these two examples by #trashgod:
example.
example.
You have a resource location problem.
Toolkit#createImage may return an empty image if the resource can not be found.
I suggest you use the ImageIO API instead, it supports a wider range of image formats, but will also throw an exception if the image is not found or can not be loaded.
How you load the image will also depend on where the image is.
If the image exists on the file system, you can simply use a File object reference, if the image is an embedded resource (within you application), you will need to use Class#getResource to obtain a URL to it.
public class TestGraphics {
public static void main(String[] args) {
new TestGraphics();
}
public TestGraphics() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new PaintTest());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PaintTest extends JPanel {
private BufferedImage image;
public PaintTest() {
setLayout(new BorderLayout());
try {
// Use this if the image exists within the file system
image = ImageIO.read(new File("/path/to/image/imageName.png"));
// Use this if the image is an embedded resource
// image = ImageIO.read(getClass().getResource("/path/to/resource/imageName.png"));
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return image == null ? super.getPreferredSize() : new Dimension (image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
int x = (getWidth() - image.getWidth()) / 2;
int y = (getHeight()- image.getHeight()) / 2;
g.drawImage(image, x, y, this);
}
}
}
}

Fast switching between two images?

I want to make an object to open mouth and close it using two images that switch quickly. I tried with a for loop but it lagged my game.
if(direction == Constant.UP){
ImageIcon i = new ImageIcon("src\\images\\pacman up.png");
image = i.getImage();
ImageIcon i2 = new ImageIcon("src\\images\\pacman left.png");
image = i2.getImage();
}
G.drawImage(image, x, y, 20,20,null);
Any animation in Swing needs to take into consideration the Event Dispatching Thread.
You should NEVER perform any action within the content of the EDT that may block it (such as loops or I/O) as this will prevent the EDT from (amongst other things) processing paint requests.
You should always use a surface capable of supporting double buffer, such as JPanel as this will help eliminate flickering
The following uses a javax.swing.Timer to switch between the two images...
public class TestPacMan {
public static void main(String[] args) {
new TestPacMan();
}
public TestPacMan() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new PacManPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PacManPane extends JPanel {
private BufferedImage pacOpened;
private BufferedImage pacClosed;
private BufferedImage frame;
private boolean opened = true;
public PacManPane() {
try {
pacOpened = ImageIO.read(new File("PC-Closed.png"));
pacClosed = ImageIO.read(new File("PC-Opened.png"));
frame = pacOpened;
} catch (IOException exp) {
exp.printStackTrace();
}
Timer timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
opened = !opened;
frame = opened ? pacOpened : pacClosed;
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (frame != null) {
int x = (getWidth() - frame.getWidth()) / 2;
int y = (getHeight() - frame.getHeight()) / 2;
g2d.drawImage(frame, x, y, this);
}
g2d.dispose();
}
}
}
don't create the icon each time. create the two images at startup and just switch back
and forth at runtime.
if(direction == Constant.UP){
image = open;
}else {
image = closed;
}
G.drawImage(image, x, y, 20,20,null);

Categories