3

I'm learning Java here and trying to get to grips with classes and how best to catch mouse events etc. for my little game, so please be patient and give my some hints.

The main class of my project extends JFrame and upon construction adds to itself an object of a class which extends JPanel. This JPanel covers the whole window and it is this I am using to paint stuff to the screen. Then I have a class called Scene which extends nothing but which stores all the references to the current objects on the screen and is responsible for compiling them all and passing them back to the JPanel. I didn't want to put the full mouse event code in the JPanel because it would be so messy so I though I'd create another class for that called MEs and let each scene have one. My thinking was, this way each mes object can access the objects in each scene easily. So my code is looking like this:

class DPanel extends JPanel {
    Scene scCurrent;

    public DPanel() {
        scCurrent = new Scene();
        addMouseMotionListener(new MouseAdapter() { 
            public void mouseMoved(MouseEvent me) { scCurrent.mes.moved(me); } 
        });
...
    }

...

but of course, inside scCurrent.mes.moved() I don't even know how to change the cursor. It doesn't recognise setCursor() in there. How can I change the cursor and access objects that are higher up the tree like I'd need to to switch scene? Or is there some other place I can tuck my mouse event handling code that will not bumph-out out my JPanel?

kleopatra
  • 51,061
  • 28
  • 99
  • 211
flea whale
  • 1,783
  • 3
  • 25
  • 38

1 Answers1

4

You are trying to separate out the control code from the view (GUI) code, and this is a good thing. A solution is to give the view code public methods that allow outside code to change its state, and give the control classes a reference to the view so that the controls (i.e., MouseListeners, MouseMotionListeners, ActionListeneres) can call these methods on a proper reference and change the view's states.

Edit 1
It may be easier just to show you an example:

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 ViewControl {

   private static void createAndShowGui() {
      View view = new View();
      Control control = new Control(view);
      view.addMouseAdapter(control);

      JFrame frame = new JFrame("ViewControl");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(view);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

@SuppressWarnings("serial")
class View extends JPanel {
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   private List<Point> points = new ArrayList<Point>();

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (points.size() > 1) {
         for (int i = 0; i < points.size() - 1; i++) {
            int x1 = points.get(i).x;
            int y1 = points.get(i).y;
            int x2 = points.get(i + 1).x;
            int y2 = points.get(i + 1).y;

            g.drawLine(x1, y1, x2, y2);
         }
      }
   }

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

   public void addMouseAdapter(MouseAdapter adapter) {
      // addMouseListener(adapter);
      addMouseMotionListener(adapter);
   }

   public void addPoint(Point p) {
      points.add(p);
      repaint();
   }
}

class Control extends MouseAdapter {
   private View view;

   public Control(View view) {
      this.view = view;
   }

   @Override
   public void mouseDragged(MouseEvent e) {
      view.addPoint(e.getPoint());
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Thanks for your reply @Hovercraft Full Of Eels, it sounds like the kind of advice I need. It sounds so elegant and simple! But how can I pass a reference onto the control classes? If I try adapting the control class to accept the reference as another variable like `scCurrent.mes.moved(this,me);` it thinks `this` means the mouseadapter – flea whale Feb 16 '12 at 02:32
  • Ahhh, by making a new class which extends `MouseAdapter` and giving it the reference when you make a new instance to it at the same level at which you make the JPanel... ingenious! Thanks @Hovercraft Full Of Eels, this is now much clearer :) – flea whale Feb 16 '12 at 02:45
  • @Jimmy: You're quite welcome! Also for a more detailed example of MVC, please see my example [here](http://stackoverflow.com/a/5533581/522444) and [here](http://stackoverflow.com/a/6088659/522444) – Hovercraft Full Of Eels Feb 16 '12 at 02:49