tags:

views:

73

answers:

5

Hi, I'm having a problem where I can't properly access my instance Point data.

I create an multi-dimensional array of GridPanels, and instantiate each with a Point. When first created, everything works as expected.

pic1

When I click on a GridPanel however, the Listener class always receives the Point from the last GridPanel that was created ( (3, 3) in this case.)

When I pass an int instead of a Point however, the int for the GridPanel that was clicked is shown (like you'd expect).

Anyone know what's going on here?

Thanks

import javax.swing.JFrame;

/**
 * Driver class.
 */
public class Test {
    /**
     * The main method.
     * @param args Command line arguments.
     */
    public static void main(String[] args) {
        JFrame frame = new JFrame("TEST");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        TestPanel panel = new TestPanel();
        frame.getContentPane().add(panel);

        frame.pack();
        frame.setVisible(true);
    }
}

import java.awt.GridLayout;
import java.awt.Point;
import javax.swing.JPanel;

/**
 * Creates a 4 by 4 grid of GridPanels.
 */
public class TestPanel extends JPanel {
    static final int ROW_SIZE = 4;
    static final int COL_SIZE = 4;
    private GridPanel[][] g = new GridPanel[ROW_SIZE][COL_SIZE];

    public TestPanel() {
        Point coords = new Point();

        setLayout(new GridLayout(ROW_SIZE, COL_SIZE));

        for (int i = 0; i < ROW_SIZE; i++) {
            for (int j = 0; j < COL_SIZE; j++) {
                coords.setLocation(i, j);
                g[i][j] = new GridPanel(coords);
                add(g[i][j]);
            }
        }
    }
}

import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 * Contains the MouseListener.
 */
public class GridPanel extends JPanel {

    private JLabel label;
    private Point p;

    public GridPanel(Point p) {
        this.p = p;
        label = new JLabel("" + p);

        add(label);

        setBackground(Color.WHITE);
        setPreferredSize(new Dimension(200, 50));

        addMouseListener(new SelectListener());
    }

    private class SelectListener extends MouseAdapter {
        public void mousePressed(MouseEvent e) {
            label.setText("" + p);
        }
    }
}
+2  A: 

The problem is that you are re-using the same point, stored in coords. You need to create a new point for each grid element. It looks to you as if each panel has a different point value stored in it because each panel has a different label. But in the line

label = new JLabel("" + p);

you are creating a String that contains the current value of p. But p can change later, and the label won't change with it.

So the easiest fix for your problem is to change the line

this.p = p;

to

this.p = new Point(p); // Create a defensive copy.

It looks like you may be currently somewhat confused about the difference between objects and fields. For example,

Point p = new Point(3, 4);
Point p2 = p;
p.x = 7;
System.out.println(p2.x);

will yield 7, as there is only one point being manipulated, though it's pointed to by two fields. Using = doesn't create a copy of the point.

(Apologies if I'm explaining things you already know!)

Zarkonnen
Yup, that's it.
Mike42
Ah man, I should of caught this.I'm still new at this, so even though I already "knew" this, the explanation definitely helped. Thank you so much!
Dean
+1  A: 

The point is and object so it is passed by reference. This means all your panels reference the same Point. Since you are changing the location on it all the time - the last will be shown.

You have to create new Point every time in the loop:

public TestPanel() {

    setLayout(new GridLayout(ROW_SIZE, COL_SIZE));

    for (int i = 0; i < ROW_SIZE; i++) {
        for (int j = 0; j < COL_SIZE; j++) {

            g[i][j] = new GridPanel(new Point(i, j));

            add(g[i][j]);
        }
    }

}
eugener
To be pedantic, the point *is* an object reference, it's not "passed by reference" which isn't possible in Java
Davy8
A: 

i have a problem if i edit and use these code?

in test.java - frame.SetSize(1200,900); in TestPanel.java -

static final int ROW_SIZE = 360; static final int COL_SIZE = 300; setSize(1200,900);

problem - grid not fit in frame.... please reply?

rahul
If I understand the question correctly, here's what is happening:- by changing ROW_SIZE and COL_SIZE, you're making a grid that is 300 columns by 360 rows.- Every spot in the grid contains a GridPanel that is 200 x 50.- 300 x 200 = 60000; 360 x 50 = 18000 - That means all your GridPanels need 60000 x 18000 to be displayed properly.
Dean
thankyou for your reply,i change setPreferredSize(new Dimension(w, h)); this is done.but in my program i need change my frame size every time. so how can fit gridpanel in frame....if frame size (1200,800), (1170,920).....
rahul
What dimensions did you change the GridPanel to?
Dean
A: 

i change setPreferredSize(new Dimension(w, h)); this is done. but in my program i need change my frame size every time. so how can fit gridpanel in that case.... if frame size (1200,800) or (1170,920) i am not using JLabel here.

rahul
A: 

thankyou for answering

in place of this frame.pack(); i use frame.setSize(W,H);

in a gridpanel add setPreferredSize(new Dimension(x,y)); setBorder(BorderFactory.createLineBorder(Color.red)); i remove JLabel where x = w / col_size; y = h / row_size;

now when i run Test.java grid are not fitted in my frame;

rahul