0

I am trying to write a Java program that when you click on a certain element in the JFrame, the background of a JLabel is changed. The function that the event handling method calls to change the background does not work when called from the event, however it does work whenever you call the method somewhere independent of any event. Does anyone know how you would go about changing the background on MouseRelease event, since using an event handling method like so doesn't work?

private void MouseReleaseEvent(java.awt.event.MouseEvent evt) {                                             
    // Do some random stuff, like a println.
    // This println works as a normal println statement should.
    System.out.println("Hello World!");
    // Now let's try the method that changes the background.
    // This method will not work within this event handler, but trying it outside
    // of it does work.
    changeBackground();
}   
  • Note: The above code is solely for showing my problem. It is not actually part of my code. I am not releasing the code because I am working on the program with a friend, and he does not want to release the code, even if it is just a small part of it with which nothing valuable can be done.

Edit: As per the request of all of those trying to help me, I have uploaded the NetBeans project workspace to FileDropper in a zip file, which you can download here. You will notice that when I call the method from the main class, it does flash another image and return to the current one as I want, but when you release the mouse from clicking on "Play", it does not call it, even though it should. Feel free to experiment with the code as you wish.

Edit 2: Since it has also been requested that I post the code for those that do not want to download the workspace, here it is:

Simon.java

package simon;

public class Simon {
    public static void main(String[] args) {
        // Load all of the other class files into this main class.
        SimonGUI SimonGUI = new SimonGUI();
        // For some reason, setting the background color doesn't work when we
        // try doing it within the GUI development environment, but it works
        // here, so that's what we are going to do.
        SimonGUI.getContentPane().setBackground(new java.awt.Color(0, 0, 0));
        // Make the form visible to the user. It is now ready for use.
        SimonGUI.setVisible(true);
        SimonGUI.playBackPattern();
    }
}

SimonGUI.java*

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package simon;

import java.awt.Component;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 *
 * @author Administrator
 */
public class SimonGUI extends javax.swing.JFrame {
    // Declare class level variables.
    boolean aboutTextVisible = false;
    boolean mainMenuVisible = true;
    boolean userResponseAllowed = false;
    private Component frame;

    /**
     * Creates new form SimonGUI
     */
    public SimonGUI() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        lblPlayButton1 = new javax.swing.JLabel();
        lblPlayButton = new javax.swing.JLabel();
        lblSimonBoard = new javax.swing.JLabel();

        lblPlayButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/simon/resources/MenuPlay.png"))); // NOI18N
        lblPlayButton1.setName("lblPlayButton"); // NOI18N

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Simon");
        setBackground(new java.awt.Color(0, 0, 0));
        setMaximumSize(new java.awt.Dimension(600, 600));
        setMinimumSize(new java.awt.Dimension(600, 600));
        setName("frmSimon"); // NOI18N
        setPreferredSize(new java.awt.Dimension(600, 600));
        setResizable(false);
        getContentPane().setLayout(null);

        lblPlayButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/simon/resources/MenuPlay.png"))); // NOI18N
        lblPlayButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        lblPlayButton.setName("lblPlayButton"); // NOI18N
        lblPlayButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                lblPlayButtonMouseReleased(evt);
            }
        });
        getContentPane().add(lblPlayButton);
        lblPlayButton.setBounds(150, 20, 317, 58);
        lblPlayButton.getAccessibleContext().setAccessibleName("lblPlayerButton");

        lblSimonBoard.setIcon(new javax.swing.ImageIcon(getClass().getResource("/simon/resources/Original.PNG"))); // NOI18N
        lblSimonBoard.setToolTipText("");
        lblSimonBoard.setFocusable(false);
        lblSimonBoard.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        lblSimonBoard.setName("lblSimon"); // NOI18N
        getContentPane().add(lblSimonBoard);
        lblSimonBoard.setBounds(-1, 93, 600, 497);
        lblSimonBoard.getAccessibleContext().setAccessibleName("lblSimon");

        getAccessibleContext().setAccessibleName("frmSimon");
        getAccessibleContext().setAccessibleDescription("");

        pack();
    }// </editor-fold>                        

    private void lblPlayButtonMouseReleased(java.awt.event.MouseEvent evt) {                                            
        // This handles the start of Simon gameplay.
        toggleBoard();
        playBackPattern();
    }                                           

    public void toggleBoard() {
        // Handles toggling between the main menu and the simon board.
        if (mainMenuVisible == true)
        {
            // Board is visible, let's toggle it off.
            lblPlayButton.setBounds(700, 700, 317, 58);
            mainMenuVisible = false;
            lblSimonBoard.setIcon(new javax.swing.ImageIcon(getClass().getResource("/simon/resources/Original.PNG")));
        }
        else
        {
            // Board is not visible, let's toggle it on.
            lblPlayButton.setBounds(120, 140, 317, 58);
            mainMenuVisible = true;
            lblSimonBoard.setIcon(new javax.swing.ImageIcon(getClass().getResource("/simon/resources/SimonBackground.PNG")));
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(SimonGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(SimonGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(SimonGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(SimonGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new SimonGUI().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify                     
    private javax.swing.JLabel lblPlayButton;
    private javax.swing.JLabel lblPlayButton1;
    public javax.swing.JLabel lblSimonBoard;
    // End of variables declaration                   

    public void flashColor(int colorID) {
        // Flash one of the colors. The value of the color that we are going to
        // flash is passed here, and the color is flashed.
        // Pause for a fraction of a second before blinking the color. In case
        // something goes wrong during the pause, we have an error which we hope
        // to never use that will catch the program's weakness.
        try {
            Thread.sleep(250);
        } catch (InterruptedException ex) {
            JOptionPane.showMessageDialog(frame,"A fatal error has caused Simon to stop working.","Simon • Fatal Error",JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        // Flash the respective color.
        if(colorID == 1) {
            // Flash Red
            lblSimonBoard.setIcon(new javax.swing.ImageIcon(getClass().getResource("/simon/resources/Red.PNG")));
        }
        else if(colorID == 2){
            // Flash Green
            lblSimonBoard.setIcon(new javax.swing.ImageIcon(getClass().getResource("/simon/resources/Green.PNG")));
        }
        else if (colorID == 3) {
            // Flash Yellow
            lblSimonBoard.setIcon(new javax.swing.ImageIcon(getClass().getResource("/simon/resources/Yellow.PNG")));
        }
        else {
            // Flash Blue
            lblSimonBoard.setIcon(new javax.swing.ImageIcon(getClass().getResource("/simon/resources/Blue.PNG")));
        }
        // Wait for a fraction of a second before we return to the regular
        // board. In case something bad happens here while we pause, we have an
        // error message that we hope will never be used.
        try {
            Thread.sleep(250);
            lblSimonBoard.setIcon(new javax.swing.ImageIcon(getClass().getResource("/simon/resources/Original.PNG")));
        } catch (InterruptedException ex) {
            JOptionPane.showMessageDialog(frame,"A fatal error has caused Simon to stop working.","Simon • Fatal Error",JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
    }
    public void userResponseEnabled(boolean responsePermitted) {
        // Toggles the class-level variable "userResponseAllowed", which
        // controls if the user can click on the buttons on the Simon board and
        // give a response.

        // Pass the value to the class-level variable.
        userResponseAllowed = responsePermitted;
    }

    // "Actual Game Code"
    int score = 0;
    ArrayList pattern = new ArrayList();
    int playerColor = 0;
    int y = 0;
    boolean correct = true;
    private SimonGUI SimonGUI;

    int certainColor = 1;
    int numberOfColors = 0;

    public void playBackPattern() {
        // Normally, the playBackPattern() method has more than just this line,
        // but for demo purposes, this line is all that is needed.
        flashColor(4);
    }
}

*Some of this code is automatically generated using the Swing GUI designer add-on for NetBeans.

PWF
  • 115
  • 1
  • 4
  • 15
  • 1
    I can think of few dozen reasons this might not work, but without a workable example, it's pointless even listing them – MadProgrammer Aug 16 '13 at 04:58
  • @MadProgrammer That's fine, but you must understand that some of us are knowledgable (like you), and some of us are n00bs (like me). Some of us know why something obvious won't work, and others to do not know that obvious thing. Would you happen to know how to do what I am trying to do? – PWF Aug 16 '13 at 05:16
  • 1
    I appreciate that we are all learns, but I don't want to waste either of our time going back on forth on what "might" be causing your problems without know more about what it is you are actually doing, because I might push you in completely the wrong direction, not helpful for either of us – MadProgrammer Aug 16 '13 at 05:18
  • 1
    You need to provide your production, but could provide a [ssccee](http://sscce.org/) instead – MadProgrammer Aug 16 '13 at 05:21
  • @MadProgrammer is right. It is useless trying to enumerate all the possible reasons. You don't need to provide the actual code, all you need to do is to provide a _sample code_ that reproduces the problem. – c.s. Aug 16 '13 at 07:55
  • @MadProgrammer Please take a look at the edit that I have made to my post. – PWF Aug 17 '13 at 17:37
  • Two things jump out at me. 1- the use of null layouts and 2- You're blocking the EDT, prefer ing it from processing UI updates? Check out [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) – MadProgrammer Aug 17 '13 at 20:39
  • @MadProgrammer Okay, so how would I implement this in my code? I am not sure I quite understand what I just read. – PWF Aug 17 '13 at 20:50

2 Answers2

2
  1. JLabel is transparent by default, have to change setOpaque()

  2. I don't know whats methods MouseReleaseEvent is, don't to redirect Swing Events (is possible and required in some cases but not for newbee),

  3. standard events implemented in MouseListener are mousePressed, mouseReleased, mouseEntered, mouseExited, mouseClicked

  4. read Oracle tutorial How to Write a Mouse Listener for working examples and various, diferrent event types

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • @c.s. Please take a look at the edit that I have made to my post. – PWF Aug 17 '13 at 17:38
  • SO doesn't works this ways, not going to debug any code, nor for code posted anywhere, only here and in runnable form, but if I correctly remember there isn't notifiers for `mouseEntered/Exited`, put there `JLabelsVariableName.repaint();` to both methods `mouseEntered/Exited` – mKorbel Aug 17 '13 at 18:39
  • [do you able to understand this answer without any my additional comments about](http://stackoverflow.com/a/7944388/714968), there is quire everything, note don't load Icons on runtime, create those Objects as local variable, loop inside and to pick up variable not loading icons with quite hard FileIO – mKorbel Aug 17 '13 at 20:26
  • I am loading the icons from resources. I do not know understand what I am supposed with creating those objects as a local variable, and I read the post, and although I see that it says not to use Thread.Sleep because it messes with something, I do not know what I am supposed to use in its place to pause for a certain amount of time before continuing. – PWF Aug 17 '13 at 20:35
  • I am loading the icons from resources. this is the same as from HDD, why repeatly, whats wrong with Swing Timer, – mKorbel Aug 17 '13 at 20:57
  • I have no idea how to use the swing timer. Also, I do not understand some of what you guys are saying. For instance, I have no idea what HDD stands for. – PWF Aug 17 '13 at 21:07
1

Based on the example code, there are, at least, two things that I can that are worrisome

  1. The use of null layouts. Every system is unique, with it's own font, screen resolution and DPI properties. To overcome this issue, and to make it easier to write sophisticated user interfaces that could work across not only different computers, but different operating systems, the layout management API was developed. It strongly recommend that you take a look at Laying Out Components Within a Container
  2. The use of Thread.sleep within the Event Dispatching Thread.

Swing is a single threaded framework. That is, it is required that all interactions and modifications to the UI take place within the context of the Event Dispatching Thread. Any actions which blocks this thread will prevent it from processing, amongst other things, paint requests.

This mean that when you execute Thread.sleep, you are prevent the EDT from updating the UI until AFTER the method you are in exits...

The simplest solution I can think of for you is to use a javax.swing.Timer. The following is a simple example which demonstrates this idea.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SimpleSimon {

    public static void main(String[] args) {
        new SimpleSimon();
    }

    public SimpleSimon() {
        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.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JLabel board;
        private Timer timer;
        private int flashCount;

        private int flashColor;
        private Image[] colors;

        private Image original;

        public TestPane() {

            colors = new Image[4];
            try {
                colors[0] = ImageIO.read(getClass().getResource("/resources/Blue.PNG"));
                colors[1] = ImageIO.read(getClass().getResource("/resources/Green.PNG"));
                colors[2] = ImageIO.read(getClass().getResource("/resources/Red.PNG"));
                colors[3] = ImageIO.read(getClass().getResource("/resources/Yellow.PNG"));
                original = ImageIO.read(getClass().getResource("/resources/Original.PNG"));
            } catch (Exception e) {
                e.printStackTrace();
            }

            setLayout(new BorderLayout());
            JButton btn = new JButton("Play");
            board = new JLabel();
            board.setHorizontalAlignment(JLabel.CENTER);
            board.setVerticalAlignment(JLabel.CENTER);
            add(board);

            timer = new Timer(250, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (flashCount == 0) {
                        board.setIcon(new ImageIcon(colors[flashColor]));
                    } else {
                        board.setIcon(new ImageIcon(original));
                        timer.stop();
                    }
                    flashCount++;
                }
            });
            timer.setRepeats(true);

            add(btn, BorderLayout.SOUTH);
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    flashCount = 0;
                    flashColor = (int)Math.round(Math.random() * 3);
                    timer.restart();
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(650, 400);
        }
    }
}

Basically, I would change your playBackPattern method to start a javax.swing.Timer which could, if you wanted it to, call your flashColor method, for example...

See Concurrency in Swing for more details.

Updated with a "call back" feature

This provides a very basic example of providing a call back feature, so that when the animation stops, it will make a call back to the specified object.

Personally, I would have preferred to do it slightly different, but it was over complicating the example...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SimpleSimon {

    public static void main(String[] args) {
        new SimpleSimon();
    }

    public SimpleSimon() {
        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.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JLabel board;
        private Timer timer;
        private int flashCount;
        private int flashTimes;

        private int flashColor;
        private Image[] colors;

        private Image original;

        private AnimationCallBack callBack;

        public TestPane() {

            colors = new Image[4];
            try {
                colors[0] = createImage(Color.BLUE);
                colors[1] = createImage(Color.GREEN);
                colors[2] = createImage(Color.RED);
                colors[3] = createImage(Color.YELLOW);
                original = createImage(Color.WHITE);
            } catch (Exception e) {
                e.printStackTrace();
            }

            setLayout(new BorderLayout());
            board = new JLabel();
            board.setHorizontalAlignment(JLabel.CENTER);
            board.setVerticalAlignment(JLabel.CENTER);
            add(board);

            timer = new Timer(250, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (flashCount < flashTimes) {
                        if (flashCount % 2 == 0) {
                            board.setIcon(new ImageIcon(colors[flashColor]));
                        } else {
                            board.setIcon(new ImageIcon(original));
                        }
                    } else {
                        board.setIcon(new ImageIcon(original));
                        timer.stop();
                        // Animation has stopped, make call back...
                        if (callBack != null) {
                            callBack.animationDone();
                        }
                    }
                    flashCount++;
                }
            });
            timer.setRepeats(true);

            JPanel buttons = new JPanel(new GridLayout(0, 2));

            final JButton btnOne = new JButton("#1");
            buttons.add(btnOne);
            btnOne.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    flashCount = 0;
                    flashTimes = 1;
                    flashColor = (int) Math.round(Math.random() * 3);
                    timer.restart();

                    btnOne.setEnabled(false);
                    // Set the call back so we know when the
                    // animation has stopped...
                    callBack = new AnimationCallBack() {
                        @Override
                        public void animationDone() {
                            btnOne.setEnabled(true);
                        }
                    };
                }
            });

            final JButton btnTwo = new JButton("#2");
            buttons.add(btnTwo);
            btnTwo.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    flashCount = 0;
                    flashTimes = 3;
                    flashColor = (int) Math.round(Math.random() * 3);
                    timer.restart();
                    btnTwo.setEnabled(false);
                    // Set the call back so we know when the
                    // animation has stopped...
                    callBack = new AnimationCallBack() {
                        @Override
                        public void animationDone() {
                            btnTwo.setEnabled(true);
                        }
                    };
                }
            });
            add(buttons, BorderLayout.SOUTH);
        }

        protected Image createImage(Color color) {

            BufferedImage img = new BufferedImage(400, 400, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = img.createGraphics();
            g2d.setColor(color);
            g2d.fillRect(0, 0, 400, 400);

            return img;

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }
    }

    public interface AnimationCallBack {
        public void animationDone();
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thank you to everyone! After some research, I have managed to get timers working, and now the blink works just as I want it to! I do not understand what is being said here about null layouts, but once I do, I will go about the difficult task of choosing an answer as accepted, even though both answers are really good. – PWF Aug 19 '13 at 03:07
  • Basically using `setLayout(null)` is not recommended. There is no way you can guarantee that the proportions of a given component will meet your needs on a system with different fonts, screen resolutions etc. The layout manager API takes a lot of the guess work out of this process – MadProgrammer Aug 19 '13 at 03:12
  • Okay, thank you. I think that I understand now, but I have one issue still remaining: how can I pause the method or event-handling method from continuing execution until the timer is stopped? – PWF Aug 19 '13 at 03:24
  • Disable the component associated with the `ActionListener` (ie `btn.setEnabled(false)` within the `actionPerformed` method. Use `btn.setEnabled(true)` when you `stop` the timer - for example. – MadProgrammer Aug 19 '13 at 03:26
  • I am not sure that I quite understand what you are saying. Whenever I disable the button, and then re-enable it, will the event handler pick up where it left off? – PWF Aug 21 '13 at 03:37
  • Maybe you explain what it is you want to achieve. Do you want to stop a user from clicking the "start" button while the timer is running? – MadProgrammer Aug 21 '13 at 03:39
  • No, I want to pause whatever method that starts the timer, and I only want it to continue execution once the timer is stopped. I only want the timer to run once, and then I want it to stop, but I have already set that up, and it works. – PWF Aug 21 '13 at 03:45
  • The problem is, if you block the calling method, you will block the EDT, again, and your application will come to a stop. A better solution would be to have the `Timer` call a method after it has completed it's work... – MadProgrammer Aug 21 '13 at 03:51
  • Okay, that would be fine. Could I have some infinite loop that the method could repeatedly run while the timer is active, and once the timer shuts off, it could exit? – PWF Aug 21 '13 at 04:03
  • Still blocking the EDT...the whole of using the `Timer` was to prevent you from block the EDT...there is NO WAY you stop the execution of the calling method that won't stop the EDT from processing updates, that's the nature of a event driven environment... – MadProgrammer Aug 21 '13 at 04:04
  • @mKorbel I suppose that I am too used to using Visual Basic. The way that the program is written, I cannot really split the code into separate methods. What is the EDT anyway? I can't even do a while loop that keeps running until the timer stops? – PWF Aug 21 '13 at 18:34
  • EDT = Event Dispatching Thread, VB has the same concept - this is why many VB based program's run so badly, they perform all there processing within the context of the main event loop, causing the program to appear as if it has hung, it stops responding to paint updates and input events. The same thing would occur here. Allow the timer to run. When you are satisfied that the timer has run enough times, within the actionPerformed method, call a new method to will continue the operation of the program. This is know as the observer pattern... – MadProgrammer Aug 21 '13 at 20:10
  • See the link to concurrency in swing for more details – MadProgrammer Aug 21 '13 at 20:10
  • But the timer is going to be needed in different contexts. By that I mean that one method will call it, and when the timer stops it will need to do one thing, but another method will call the same timer, and it will need something else to be done. Also, the two methods that run before and after were supposed to be part of a loop. – PWF Aug 22 '13 at 19:32
  • I have no idea how to do that. My knowledge of Java is not advanced enough for this. I have researched it, but I haven't found anything. – PWF Aug 23 '13 at 01:35
  • As I said, this is a very basic example. I would prefer to have had made my own `Timer` implementation which took a reference to the `AnimationCallBack`, but the it raised a bunch of questions about how to update the animation flags and a like, so I went for a simple example – MadProgrammer Aug 23 '13 at 04:16
  • Looking over your code, I believe that I understand the concept of the code, but I think that I may be missing why some of the code is where it is. I am going to try to implement this in my program, but I may ask for more help. - Yeah, I am not sure about everything that is new to your program code. I have some of it, but not all of it. By the way, thanks for your continued help. I know that there is an awful lot of spoon feeding going on here. – PWF Aug 23 '13 at 04:24
  • Whenever I put in the line of code `private AnimationCallBack callBack;`, NetBeans suggests that I create an AnimationCallBack class. – PWF Aug 23 '13 at 04:33
  • Right at the bottom of my example, there is an `interface` called `AnimationCallBack`, you need to either create it as a inner interface (as I did in the example) or as a external interface in it's own file (called `AnimationCallBack`, funny enough) – MadProgrammer Aug 23 '13 at 04:35
  • A interface is a type of contract that says "any object the implements gurentees to provide implementations for the following methods", see [What is an interface](http://docs.oracle.com/javase/tutorial/java/concepts/interface.html) for more details. Essentially, I have a class instance variable call `callBack`, which assign an instance/implementation of `AnimationCallBack` to before I start the timer. When the timer completes it's work and stops, I simply call `callBack.animationDone()`. Look in the `actionPerfomed` method of the timer ;) – MadProgrammer Aug 23 '13 at 04:50
  • Okay, thanks. I did not notice that when I was looking through your code. I am still confused about `animationDone()`. It appears as though you have multiple declarations of it. I am also having an issue understanding how you are plumbing `animationDone()` into the timer so that it only runs once the timer is stopped. Once I figure out what the usage of `animationDone()` is and get this thing working, I hope that I will have a working program, and I will then finally be done bother you. – PWF Aug 23 '13 at 04:51
  • My timer can repeat `n` number of times, so I'm watching for an "escape" count. Once it's run as many times as I want, I manually stop the timer and call `animationDone` – MadProgrammer Aug 23 '13 at 04:54
  • Okay, but why does it look like you have multiple declarations of `animationDone()`? – PWF Aug 24 '13 at 01:19
  • Because I do. The `AnimationCallback` is an interface, it can not be instantiated without the contract of the interface begin fulfilled (ie the `animationDone` method begin implemented). So each button has it's own implementation, to do different things when the animation is done, which is what you've being asking for ;) – MadProgrammer Aug 24 '13 at 01:35
  • Yes, that is what I have been asking for, but I did not realize that you could do it the way that you are. – PWF Aug 24 '13 at 01:40