Results 1 to 6 of 6
- 04-14-2010, 04:53 AM #1
Member
- Join Date
- Apr 2010
- Posts
- 3
- Rep Power
- 0
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().
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.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'd appreciate any help!Last edited by Samurai413x; 04-14-2010 at 05:14 AM. Reason: SOLVED
-
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);
- 04-14-2010, 05:11 AM #3
Member
- Join Date
- Apr 2010
- Posts
- 3
- Rep Power
- 0
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.
-
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.
- 04-14-2010, 05:17 AM #5
Member
- Join Date
- Apr 2010
- Posts
- 3
- Rep Power
- 0
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?
-
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
-
help with Swing Timer animation
By tomas1991 in forum New To JavaReplies: 7Last Post: 03-19-2010, 09:06 AM -
Redraw panel in timer event
By knuth in forum Advanced JavaReplies: 6Last Post: 10-03-2009, 07:39 PM -
can i set a timer delay on mouseEntered event
By chan in forum AWT / SwingReplies: 1Last Post: 08-30-2009, 05:55 AM -
Timer on swing
By finzaiko in forum AWT / SwingReplies: 3Last Post: 04-02-2009, 07:45 AM -
Error: Exception during event dispatch!
By Javid in forum AWT / SwingReplies: 1Last Post: 08-02-2008, 01:20 PM


LinkBack URL
About LinkBacks
Reply With Quote

Bookmarks