Results 1 to 6 of 6
  1. #1
    Samurai413x is offline Member
    Join Date
    Apr 2010
    Posts
    3
    Rep Power
    0

    Default SOLVED Swing Timer & MouseListener not getting along- Multithreading? Event Dispatch?

    I'm having some issues with getting a Swing Timer and a MouseListener to work together. What I have is basically a GUI that is regularly repainting to update game graphics, controlled by the Swing Timer, and a MouseListener that should register clicks and put a small circle (star) on the GUI wherever it's clicked.

    I'm using a Vector of Star objects to keep track of them, but the problem seems to be that the MouseListener thinks the stars exist, but the Swing Timer doesnt. In mouseClicked(), the Vector of Stars will show up as having a size of 3 or whatever, but in actionPerformed() always says it's size is zero. I can't get mouseClicked() to permanently change any member variables of the class.

    Here is the class in question, I won't include the other classes for now since there are a lot of them. My main() just creates an instance of this class and calls createAndShowGUI().

    Java Code:
    package theskyabove;
    
    import java.awt.*;
    import java.awt.event.*;
    import java.util.Vector;
    import javax.swing.*;
    
    public class SkyPanel extends JPanel implements MouseListener, ActionListener
    
    {
        private JFrame frame_ ;
        private Sun sun_;
        private Moon moon_;
        private Vector<Star> stars_;
        private Vector<Cloud> clouds_;
        private int screenWidth_;
        private int screenHeight_;
        private Display myDisp_;
        private Timer timer_;
    
        public SkyPanel()
        {
            super(new GridLayout(0,1));
            frame_ = new JFrame();
            sun_ = new Sun(0,350);
            moon_ = new Moon(0,-350);
            stars_ = new Vector<Star>();
            clouds_ = new Vector<Cloud>();
            screenWidth_=1000;
            screenHeight_=700;
            myDisp_ = new Display();
            timer_ = new Timer(5000, this);
            //Register for mouse events on blankArea and the panel.
            frame_.addMouseListener(this);
            addMouseListener(this);
            setPreferredSize(new Dimension(450, 450));
        }
    
        private int xToScreen (double x)
        {
            return (int)((screenWidth_/2) + x);
        }
    
        private int yToScreen (double y)
        {
            return (int)((screenHeight_/2) - y);
        }
        public void createAndShowGUI()
        {
            timer_.setInitialDelay(0);
            timer_.start();
            //Create and set up the window.
            frame_.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            //Create and set up the content pane.
            JComponent newContentPane = new SkyPanel();
            newContentPane.setOpaque(true); //content panes must be opaque
            frame_.setContentPane(newContentPane);
    
            //Display the window.
            frame_.pack();                              //GUI is now realized
            frame_.add(myDisp_);
            frame_.setSize(screenWidth_, screenHeight_);
            frame_.setVisible(true);
        }
    
        //This should be automatically invoked in event dispatch
        public void actionPerformed(ActionEvent e) {
            System.out.println("Actionperformed called");
            sun_.move();
            moon_.move();
    //        System.out.println("At this tick number of stars: " + stars_.size());
            //This is the root problem, the stars_ here is almost like its talking to a different array than the one below
            myDisp_.update(xToScreen(sun_.getX()), yToScreen(sun_.getY()),
                xToScreen(moon_.getX()), yToScreen(moon_.getY()), stars_);
    
        }
       
        //This is unable to change anything permanently, but the println will output
        public void mouseClicked(MouseEvent e) {
            System.out.println("Mouseclicked called");
            stars_.add(new Star(e.getX(), e.getY()));
            timer_.setDelay(50);
    //        System.out.println("At mouse click, number of stars: " + stars_.size());
            myDisp_.update(xToScreen(sun_.getX()), yToScreen(sun_.getY()),
                            xToScreen(moon_.getX()), yToScreen(moon_.getY()), stars_);
        }
    
        public void mousePressed(MouseEvent e) {
    //        System.out.println("Something happened.");
        }
    
        public void mouseReleased(MouseEvent e) {
    //        System.out.println("Something happened.");
        }
    
        public void mouseEntered(MouseEvent e) {
    //        System.out.println("Something happened.");
        }
    
        public void mouseExited(MouseEvent e) {
    //        System.out.println("Something happened.");
        }
    
    }
    I'm thinking this has something to do with multithreading/synchronization/the event dispatch thread. I've read up on them, but nothing's helped me solve the problem yet; admittedly I understand these things in a broad sense but not down to the nitty gritty. I'm under the impression that maybe mouseClicked() and actonPerformed() are just being called by two separate threads that never synchronize their information, but I have no idea how to rectify that.

    I'd appreciate any help!
    Last edited by Samurai413x; 04-14-2010 at 06:14 AM. Reason: SOLVED

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    I think that this has little to do with multi-threading and possibly more to do with multiple SkyPanels, one that has the Timer and the other that has the MouseListener. So changes in the Vector (shouldn't this be an ArrayList) in one will not be reflected in the other:

    Java Code:
        public void createAndShowGUI()
        {
            // **** the timer uses the Vector from [i]this[/i] SkyPanel
            timer_.setInitialDelay(0);
    
            timer_.start();
            frame_.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            // ****** while the newContentPane is an entirely different SkyPanel with a 
            // ****** completely distinct Vector and MouseListener.
            JComponent newContentPane = [color="red"]new SkyPanel();[/color]
            newContentPane.setOpaque(true); //content panes must be opaque
            frame_.setContentPane(newContentPane);

  3. #3
    Samurai413x is offline Member
    Join Date
    Apr 2010
    Posts
    3
    Rep Power
    0

    Default

    That was it! Shows what happens when you copy paste code from tutorials that you don't really understand. Swapped that highlighted "new SkyPanel()" for a "this" and it worked fine.

    Thank you so much, you are my hero. I might actually graduate college because of you.

  4. #4
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    You're welcome. And also do yourself a favor and don't have that class implement ActionListener nor MouseListener. Use anonymous inner classes or private inner classes for your listeners since you're asking your poor SkyPanel class to do too much otherwise and it will be a mess to debug.

  5. #5
    Samurai413x is offline Member
    Join Date
    Apr 2010
    Posts
    3
    Rep Power
    0

    Default

    Ok - I understand your logic, but have no idea what you're talking about with inner classes for listeners. Any reference you'd recommend or should I JFGI?

  6. #6
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    I'm not sure if the Sun tutorials go over anonymous inner classes or not, but a quick search will tell you. Either that, or yeah, Google Java anonymous inner class tutorial.

    For e.g.,
    Java Code:
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.swing.*;
    
    public class Fu2 extends JPanel {
      private static final Dimension MAIN_SIZE = new Dimension(400, 300);
      private static final int RADIUS = 8;
      private List<Point> pointList = new ArrayList<Point>();
    
      public Fu2() {
        setPreferredSize(MAIN_SIZE);
        
        // **** here is where I add an anonymous inner MouseListener object
        addMouseListener(new MouseAdapter() {
          @Override
          public void mousePressed(MouseEvent e) {
            pointList.add(e.getPoint());
            repaint();
          }
        });
      }
      
      @Override
      protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (Point point : pointList) {
          g.setColor(Color.blue);
          int x = point.x - RADIUS;
          int y = point.y - RADIUS;
          int width = 2*RADIUS;
          int height = width;
          
          g.fillOval(x, y, width, height);
        }
      }
    
      private static void createAndShowUI() {
        JFrame frame = new JFrame("Fu2");
        frame.getContentPane().add(new Fu2());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    
      public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
          public void run() {
            createAndShowUI();
          }
        });
      }
    }

Similar Threads

  1. help with Swing Timer animation
    By tomas1991 in forum New To Java
    Replies: 7
    Last Post: 03-19-2010, 10:06 AM
  2. Redraw panel in timer event
    By knuth in forum Advanced Java
    Replies: 6
    Last Post: 10-03-2009, 08:39 PM
  3. can i set a timer delay on mouseEntered event
    By chan in forum AWT / Swing
    Replies: 1
    Last Post: 08-30-2009, 06:55 AM
  4. Timer on swing
    By finzaiko in forum AWT / Swing
    Replies: 3
    Last Post: 04-02-2009, 08:45 AM
  5. Error: Exception during event dispatch!
    By Javid in forum AWT / Swing
    Replies: 1
    Last Post: 08-02-2008, 02:20 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •