2010-02-18 8 views
3

J'ai un problème où je ne peux pas accéder correctement à mes données de point d'instance.Les points ne sont pas correctement lus par MouseListener

Je crée un tableau multi-dimensionnel de GridPanels et instancie chacun avec un point. Lors de sa création, tout fonctionne comme prévu.

pic1 http://img.skitch.com/20100218-fciwr7t73ci2gajafmfxa2yf9q.jpg

Lorsque je clique sur un GridPanel cependant, la classe Listener reçoit toujours le point des dernières GridPanel qui a été créé ((3, 3) dans ce cas.)

Quand je passer un int au lieu d'un point cependant, l'int pour le GridPanel qui a été cliqué est montré (comme vous vous en doutez).

Quelqu'un sait ce qui se passe ici?

Merci

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); 
     } 
    } 
} 

Répondre

2

Le problème est que vous réutilisez le même point, stocké dans coords. Vous devez créer un nouveau point pour chaque élément de la grille. Il vous semble que chaque panneau a une valeur de point différente stockée car chaque panneau a une étiquette différente. Mais dans la ligne

label = new JLabel("" + p); 

vous créez une chaîne qui contient la valeur actuelle de p. Mais p peut changer plus tard, et l'étiquette ne changera pas avec elle.

donc le plus facile correctif pour votre problème est de changer la ligne

this.p = p; 

à

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

Il semble que vous soyez actuellement un peu confus au sujet de la différence entre les objets et les champs. Par exemple,

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

produira 7, car il n'y a qu'un seul point d'être manipulé, mais il est pointé par deux champs. Utiliser = ne crée pas de copie du point.

(Toutes mes excuses si je vous explique les choses que vous connaissez déjà!)

+0

Ouais, c'est tout. – Mike42

+0

Ah mec, je devrais d'attrapé ceci. Je suis encore nouveau à ce sujet, donc même si je "connaissais" déjà cela, l'explication a certainement aidé. Merci beaucoup! – Dean

1

Le point est et de l'objet de sorte qu'il est passé par référence. Cela signifie que tous vos panneaux référencent le même point. Puisque vous changez l'emplacement tout le temps, le dernier sera affiché.

Vous devez créer de nouveaux points à chaque fois dans la boucle:

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]); 
     } 
    } 

} 
+0

Pour être pédant, le point * est * une référence d'objet, ce n'est pas "passé par référence" ce qui n'est pas possible en Java – Davy8

0

je change setPreferredSize (nouvelle dimension (w, h)); c'est fait. mais dans mon programme j'ai besoin de changer la taille de mon cadre à chaque fois. Alors, comment peut-on adapter grillepanel dans ce cas .... si la taille de l'image (1200,800) ou (1170,920) je n'utilise pas JLabel ici.

0

thankyou pour répondre

en place de ce frame.pack(); J'utilise frame.setSize (W, H); Dans un panneau de grille, ajoutez setPreferredSize (new Dimension (x, y)); setBorder (BorderFactory.createLineBorder (Color.red)); je supprime JLabel où x = w/col_size; y = h/row_size;

maintenant quand je cours la grille Test.java ne sont pas montés dans mon cadre;

Questions connexes