Java pause program execution - java

I have a method that updates part of the user interface. After this method is called I want the entire program to sleep for say 1 second. I do not want to run any code during this time, just simply pause the entire execution. What would be the best way of achieving this?
My reason is this, I am updating the GUI quite a bit and I want the user to see the change before the next change is made.

If you want the updates to be spaced out, you've better of using something like a javax.swing.Timer. This will allow to schedule regular updates without causing the UI to look like it's crashed/hung.
This example will update the UI every 250 milli seconds
public class TestTimerUpdate {
public static void main(String[] args) {
new TestTimerUpdate();
}
public TestTimerUpdate() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TimerPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected class TimerPane extends JPanel {
private int updates = 0;
public TimerPane() {
Timer timer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
updates++;
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
#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 = "I've being updated " + Integer.toString(updates) + " times";
FontMetrics fm = g2d.getFontMetrics();
int x = (getWidth() - fm.stringWidth(text)) / 2;
int y = ((getHeight() - fm.getHeight()) / 2) + fm.getAscent();
g2d.drawString(text, x, y);
g2d.dispose();
}
}
}
You can also have a look at How can I make a clock tick? which demonstrates the same idea

Related

Java how to move a paint componenet [duplicate]

I'm trying to move the boat on the x-axis (without the keyboard yet). How can I relate the movement/ animation to the boat.png and not to any other image?
public class Mama extends Applet implements Runnable {
int width, height;
int x = 200;
int y = 200;
int dx = 1;
Image img1, img2, img3, img4;
#Override
public void init(){
setSize(627, 373);
Thread t = new Thread(this);
img1 = getImage(getCodeBase(),"Background.png");
img2 = getImage(getCodeBase(), "boat.png");
img3 = getImage(getCodeBase(), "LeftPalm.png");
img4 = getImage(getCodeBase(), "RightPalm.png");
}
#Override
public void paint(Graphics g){
g.drawImage(img1, 0, 0, this);
g.drawImage(img2, 200, 200, this);
g.drawImage(img3, 40, 100, this);
g.drawImage(img4, 450, 130, this);
}
#Override
public void run() {
while(true){
x += dx;
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
System.out.println("Thread generates an error.");
}
}
}
}
There are a few things that stand out...
The "Problem"
As has already been stated, you need to supply variable arguments to the image drawing process. g.drawImage(img2, x, y, this);, this will allow you define where the image should be painted.
While you've implemented Runnable, you've actually not started any threads to call it. This means, nothing is actually changing the variables.
In you start method, you should be calling something like new Thread(this).start().
Recommendations
Although you've tagged the question as Swing, you're using AWT components. This isn't recommended (in fact applets are generally discouraged as they are troublesome - IMHO). The other problem, as you are bound to find out shortly, is they are not double buffered, this generally leads to flickering when performing animation, which isn't desirable.
As a side note, it is also discouraged to override the paint method of top level containers like Applet. Top level containers tend to contain a number additional components, by overriding the paint method like this, you destroy this setup. Also, top level containers don't tend to be double buffered either.
The example below uses a JFrame, but it wouldn't take much to convert it to use a JApplet (just drop the AnimationPanel on to it. This is another reason why extending from top level containers is generally discouraged ;)
public class AnimatedBoat {
public static void main(String[] args) {
new AnimatedBoat();
}
public AnimatedBoat() {
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 AnimationPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class AnimationPane extends JPanel {
private BufferedImage boat;
private int xPos = 0;
private int direction = 1;
public AnimationPane() {
try {
boat = ImageIO.read(new File("boat.png"));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += direction;
if (xPos + boat.getWidth() > getWidth()) {
xPos = getWidth() - boat.getWidth();
direction *= -1;
} else if (xPos < 0) {
xPos = 0;
direction *= -1;
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return boat == null ? super.getPreferredSize() : new Dimension(boat.getWidth() * 4, boat.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int y = getHeight() - boat.getHeight();
g.drawImage(boat, xPos, y, this);
}
}
}
You need to replace g.drawImage(img2, 200, 200, this); with g.drawImage(img2, x, y, this);

How to move an image (animation)?

I'm trying to move the boat on the x-axis (without the keyboard yet). How can I relate the movement/ animation to the boat.png and not to any other image?
public class Mama extends Applet implements Runnable {
int width, height;
int x = 200;
int y = 200;
int dx = 1;
Image img1, img2, img3, img4;
#Override
public void init(){
setSize(627, 373);
Thread t = new Thread(this);
img1 = getImage(getCodeBase(),"Background.png");
img2 = getImage(getCodeBase(), "boat.png");
img3 = getImage(getCodeBase(), "LeftPalm.png");
img4 = getImage(getCodeBase(), "RightPalm.png");
}
#Override
public void paint(Graphics g){
g.drawImage(img1, 0, 0, this);
g.drawImage(img2, 200, 200, this);
g.drawImage(img3, 40, 100, this);
g.drawImage(img4, 450, 130, this);
}
#Override
public void run() {
while(true){
x += dx;
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
System.out.println("Thread generates an error.");
}
}
}
}
There are a few things that stand out...
The "Problem"
As has already been stated, you need to supply variable arguments to the image drawing process. g.drawImage(img2, x, y, this);, this will allow you define where the image should be painted.
While you've implemented Runnable, you've actually not started any threads to call it. This means, nothing is actually changing the variables.
In you start method, you should be calling something like new Thread(this).start().
Recommendations
Although you've tagged the question as Swing, you're using AWT components. This isn't recommended (in fact applets are generally discouraged as they are troublesome - IMHO). The other problem, as you are bound to find out shortly, is they are not double buffered, this generally leads to flickering when performing animation, which isn't desirable.
As a side note, it is also discouraged to override the paint method of top level containers like Applet. Top level containers tend to contain a number additional components, by overriding the paint method like this, you destroy this setup. Also, top level containers don't tend to be double buffered either.
The example below uses a JFrame, but it wouldn't take much to convert it to use a JApplet (just drop the AnimationPanel on to it. This is another reason why extending from top level containers is generally discouraged ;)
public class AnimatedBoat {
public static void main(String[] args) {
new AnimatedBoat();
}
public AnimatedBoat() {
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 AnimationPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class AnimationPane extends JPanel {
private BufferedImage boat;
private int xPos = 0;
private int direction = 1;
public AnimationPane() {
try {
boat = ImageIO.read(new File("boat.png"));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += direction;
if (xPos + boat.getWidth() > getWidth()) {
xPos = getWidth() - boat.getWidth();
direction *= -1;
} else if (xPos < 0) {
xPos = 0;
direction *= -1;
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return boat == null ? super.getPreferredSize() : new Dimension(boat.getWidth() * 4, boat.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int y = getHeight() - boat.getHeight();
g.drawImage(boat, xPos, y, this);
}
}
}
You need to replace g.drawImage(img2, 200, 200, this); with g.drawImage(img2, x, y, this);

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.

Why doesn't the circle appear when I click?

I have to use the Console class in HoltSoft's Ready to Program. I'm not supposed to use swing, so if I can't do it without swing, kindly ignore this.
//imports
import java.awt.*;
import java.awt.event.*;
import hsa.*;
public class DrawLines extends Panel implements MouseListener, MouseMotionListener
{
Console c;
int startX, startY, prevX, prevY; //mouse coordinates
private boolean dragging; //whether or not the mouse is being dragged
MouseEvent e;
public DrawLines ()
{
c = new Console (); //creates console window
addMouseListener (this); //detects press/release
addMouseMotionListener (this);//detects dragging
}
public void mousePressed (MouseEvent e)
{
while (!dragging)
{
try
{
startX = e.getX ();//get the
startY = e.getY ();//original co-ordinates
dragging = true;
}
catch (NullPointerException q) //because I kept getting this error
{
}
}
}
public void mouseDragged (MouseEvent e)
{
while (dragging)
{
try
{
int x = e.getX (); //gets and
int y = e.getY (); //updates
prevX = x; //the mouse
prevY = y; //coordinates
}
catch (NullPointerException q)//because I kept getting this error
{
}
}
}
public void mouseReleased (MouseEvent e)
{
dragging = false; //stopped dragging
}
public void drawTheLine ()
{
mousePressed (e);
mouseDragged (e);
c.setColor (Color.black);
c.fillOval (prevX, prevY, 50, 50); //draws a circle where the mouse is
mouseReleased (e);
}
public void mouseMoved (MouseEvent e){}
public void mouseEntered (MouseEvent e){}
public void mouseExited (MouseEvent e){}
public void mouseClicked (MouseEvent e){}
public static void main (String[] args)
{
DrawLines a = new DrawLines ();
a.drawTheLine ();
}
}
I've been trying to use MouseListener and MouseMotionListener in Console. At first, the program kept giving me errors, so I added the try/catch structures. Now it doesn't crash, but nothing appears on the screen. Why? Help?
If I shouldn't use try/catch to just ignore it, what should I do?
I'm not allowed to use anything other than Console() for this program. It's a course assignment.
Look at this:
public void drawTheLine ()
{
while (true)
{
mousePressed (e);
mouseDragged (e);
c.setColor (Color.black);
c.fillOval (prevX, prevY, 50, 50); //draws a circle where the mouse is
mouseReleased (e);
}
}
The parameter "e" you're passing is null. It is declared here:
public class DrawLines extends Panel
implements MouseListener, MouseMotionListener
{
MouseEvent e; // IT IS NEVER SET TO ANYTHING! IT IS NULL!!!
Somewhere in your constructor you should do this so it's no longer null:
e = (something);
Swing is an event driven system and is a single threaded system.
This means that your application "waits" for events to occur (which is taken care for you by the Event Dispatching Thread) and that anyone that blocks the EDT, like, loops, long running processes or blocking IO, will prevent you application from receiving notification of those events, making impossible for you application to run.
So, if we have a look at this...
while (true)
{
mousePressed (e);
mouseDragged (e);
c.setColor (Color.black);
c.fillOval (prevX, prevY, 50, 50);
mouseReleased (e);
}
}
It suggest that...one, you don't understand how events are generated in Swing and two, how the EDT actually works.
Unlike some UI frameworks, you are not required to implement a event loop, this is taken care of you by Swing. Blocking the EDT like this, will prevent it for processing events
Instead, remove the drawLineMethod as it is doing absolute nothing for you and replace you main method with something like...
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new DrawLines());
// I prefer pack, but you've not specified a preferred size for your panel...
//frame.pack();
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
Now. I have no idea what the Console class is or does, but in your mouse event methods, you will need to update it so that it can update it's output...
Updated with example
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 (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new DrawPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DrawPane extends JPanel {
private Point center;
private int radius;
public DrawPane() {
MouseAdapter handler = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
center = e.getPoint();
radius = 0;
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
int width = Math.max(e.getX(), center.x) - Math.min(e.getX(), center.x);
int height = Math.max(e.getY(), center.y) - Math.min(e.getY(), center.y);
radius = Math.max(width, height);
repaint();
}
};
addMouseListener(handler);
addMouseMotionListener(handler);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (center != null) {
g.setColor(Color.RED);
g.fillOval(center.x - 2, center.y - 2, 4, 4);
g.drawOval(center.x - (radius / 2), center.y - (radius / 2), radius, radius);
}
}
}
}
I would suggest that you take the time to have a read through...
Creating a GUI with Swing to get an understanding of the overall basics of Swing
Performing Custom Painting to get an understanding of how custom painting is actually performed in Swing
Painting in AWT and Swing as all developers wishing to perform custom painting in Swing need to understand how this works...
Update with a pure AWT version
As it was pointed out to me that the OP was using AWT instead of Swing, why, cause they seem to be able to ...
public class DrawCircleAWT {
public static void main(String[] args) {
new DrawCircleAWT();
}
public DrawCircleAWT() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Frame frame = new Frame("Testing");
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setLayout(new BorderLayout());
frame.add(new DrawPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DrawPane extends Panel {
private Point center;
private int radius;
public DrawPane() {
MouseAdapter handler = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
center = e.getPoint();
radius = 0;
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
int width = Math.max(e.getX(), center.x) - Math.min(e.getX(), center.x);
int height = Math.max(e.getY(), center.y) - Math.min(e.getY(), center.y);
radius = Math.max(width, height);
repaint();
}
};
addMouseListener(handler);
addMouseMotionListener(handler);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
public void paint(Graphics g) {
super.paint(g);
if (center != null) {
g.setColor(Color.RED);
g.fillOval(center.x - 2, center.y - 2, 4, 4);
g.drawOval(center.x - (radius / 2), center.y - (radius / 2), radius, radius);
}
}
}
}

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