2013-04-24 9 views
5

Próbuję stworzyć grę Java z siatką 10 x 10 składającą się z komórek. Siatka wygląda to liks:Jak używać MouseListener do znalezienia konkretnej komórki w siatce

klasa
public class Grid extends JPanel implements MouseListener { 
    public static final int GRID_SIZE = 10; 

    public Grid() { 
     setPreferredSize(new Dimension(300, 300)); 
     setLayout(new GridLayout(GRID_SIZE, GRID_SIZE)); 

     for (int x = 0; x < GRID_SIZE; x++) 
      for (int y = 0; y < GRID_SIZE; y++) 
       add(new Cell(x, y)); 
     addMouseListener(this); 
    } 

// All Mouse Listener methods are in here. 

Cela wygląda następująco:

public class Cell extends JPanel { 

    public static final int CELL_SIZE = 1; 
    private int xPos; 
    private int yPos; 

    public Cell (int x, int y) { 
     xPos = x; 
     yPos = y; 
     setOpaque(true); 
     setBorder(BorderFactory.createBevelBorder(CELL_SIZE)); 
     setBackground(new Color(105, 120, 105)); 
     setPreferredSize(new Dimension(CELL_SIZE, CELL_SIZE)); 
    } 

    // Getter methods for x and y. 

Mój problem jest to, że jestem teraz próbuje wdrożyć MouseListeners w klasie sieci. Zdałem sobie sprawę, że chociaż mogę zwrócić współrzędne X i Y siatki, nie mogę manipulować komórkami. Zakładam, że dzieje się tak dlatego, że gdy tworzyłem je w Grid, tworzę 100 losowych komórek bez identyfikatorów, więc nie mam możliwości bezpośredniego dostępu do nich.

Czy ktoś może mi doradzić w tej sprawie? Czy muszę dokonać przeglądu mojego kodu i sposobu, w jaki tworzę komórki? Czy jestem okropnie głupia i brakuje im oczywistego sposobu na dostęp do nich? Dzięki

Odpowiedz

2

Można użyć wzoru adaptera, jak pokazano poniżej. W ten sposób można osobno dodać słuchacza do każdej komórki siatki, ale nadal obsługuje zdarzenia z Grid.

Zauważ, że Grid nie implementuje już MouseListener, jest to teraz obsługiwane przez komórki.

public class Grid extends JPanel { 
    public static final int GRID_SIZE = 10; 

    public Grid() { 
     setPreferredSize(new Dimension(300, 300)); 
     setLayout(new GridLayout(GRID_SIZE, GRID_SIZE)); 

     for (int x = 0; x < GRID_SIZE; x++) { 
      for (int y = 0; y < GRID_SIZE; y++) { 
       final Cell cell = new Cell(x, y); 
       add(cell); 
       cell.addMouseListener(new MouseListener() { 
        public void mouseClicked(MouseEvent e) { 
         click(e, cell); 
        } 
        // other mouse listener functions 
       }); 
      } 
     }   
    } 

    public void click(MouseEvent e, Cell cell) { 
     // handle the event, for instance 
     cell.setBackground(Color.blue); 
    } 

    // handlers for the other mouse events 
} 

Podklasa mogłyby zastąpić to jako:

public class EnemyGrid extends Grid { 
    public void click(MouseEvent e, Cell cell) { 
     cell.setBackground(Color.red); 
    } 
} 
+0

To naprawdę przydatny fragment kodu - dziękuję! Czy mogę zadać pytanie uzupełniające - faktycznie tworzę dwie podklasy z Grid: OwnGrid i EnemyGrid. Oboje początkowo przesłonili metody MouseListener, które były zawarte w klasie Grid. Z nową zaproponowaną strukturą, w jaki sposób mogę zastąpić te metody w podklasach Grid? –

+0

@AndrewMartin Nie jestem pewien, czy rozumiem, że poprawnie, ale jeśli chcesz obsługiwać zdarzenia różnie w obu podklasach, możesz po prostu zastąpić "mouseClicked (MouseEvent e, Cell cell)" –

+0

"jak mogę zastąpić te metody w podklasy Grid "nie jest to łatwa praca (ponieważ jest to możliwe bez żadnego problemu), możesz stracić w JCOmponents hierarchii, jedną z wad jest dziedziczenie, [użyj kompozycji zamiast] (http://www.javaworld.com/ jw-11-1998/jw-11-techniques.html) – mKorbel

2
+0

Dzięki za odpowiedź i komentarz do drugiego postu. Nie znam kompozycji. Pozbyłem się "rozszerzenia" części podklasy i zamiast tego stworzyłem zrobioną "prywatną siatkę siatki = nową siatkę()" - jak mogę teraz połączyć to z mouseListeners itp? –

+0

[zobacz inny JButton i ActionListener] (http://stackoverflow.com/a/9007348/714968), ponownie zmień JButton na JPanel i ActionListener na MouseListener tylko jako ogólny i działający przykład kodu – mKorbel

+0

Proponuję użyć putClientProperty dla gry oparte na siatce, np puzzle, sudoku, .... – mKorbel

1

Najbardziej oczywistym sposobem byłoby przenieść MouseListener na samej klasie Cell.

Druga opcja, o której mogę pomyśleć to użycie java.awt.Container.getComponentAt(int, int).

+0

lub SwingUtilities – mKorbel

Powiązane problemy