2012-10-17 9 views
5

Mam klasę o nazwie Shape, która dziedziczy po JPanel.Kliknięcie narysowanego obiektu

Liczba podklas z kolei rozszerza klasy Shape, po jednym dla każdego rodzaju kształtu.

Każdy kształt ma własną zmienioną metodę paint(), która rysuje odpowiedni kształt.

Chciałbym móc kliknąć dowolny kształt i próbuję teraz zaimplementować tę logikę. Zwróć uwagę, że każdy kształt został dodany do tablicy LISTA.

Jednak instrukcja zawiera zawsze zwraca wartość false, nawet jeśli wyraźnie kliknąłem wewnątrz kształtu.

Wszelkie pomysły?

+0

OK, planujecie coś takiego składnika kształtów malować? – Takarakaka

+0

Jakie kształty? Musisz zaimplementować metodę "zawiera". To nie będzie generować się z ich metody "malowania". –

+0

Czy możesz uprzejmie opracować proszę @JanDvorak? Do tej pory program działa, dzięki czemu na ekranie rysuje się wiele kształtów. Mój problem polega na tym, że nie mogę kliknąć żadnego z kształtów. –

Odpowiedz

10

nigdy przesłonić paint() w JPanel raczej paintComponent(..)

Nie jestem pewien, rozumiem jednak zrobiłem krótki przykład, który mam nadzieję pomoże. Zasadniczo jest to prosta JFrame z DrawingPanel (moja własna klasa, która rozszerza JPanel i kształty są rysowane na). Ten panel utworzy kształty (tylko 2 do testowania) dodaj je do ArrayList i narysuj je do pętli JPanel poprzez paintComponent(..) i for, a także do sprawdzenia użytkownika mouseClicked(..) evnets na JPanel. Kiedy kliknięcia wykonane my iterację każdego Shape w ArrayList i sprawdzić, czy Shape zawiera punkt, czy nie, a jeśli tak, drukuje jego nazwę klasy i wykorzystuje instance of, by sprawdzić, jaki rodzaj Shape kliknięciu i drukuje odpowiedni komunikat:

enter image description here

Wyjście (po kliknięciu): oba kształty

kliknął java.awt.geom.Rectangle2D $ Podwójne

Kliknięcie prostokąta

Kliknięto plik java.awt.geom.Ellipse2D $ Podwójne

Kliknięto krąg

ShapeClicker.java:

import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Shape; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Rectangle2D; 
import java.util.ArrayList; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class ShapeClicker { 

    public ShapeClicker() { 
     JFrame frame = new JFrame(); 
     frame.setTitle("Shape Clicker"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setResizable(false); 

     initComponents(frame); 

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

    public static void main(String[] args) { 

     //create frame and components on EDT 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new ShapeClicker(); 
      } 
     }); 
    } 

    private void initComponents(JFrame frame) { 
     frame.add(new ShapePanel()); 
    } 
} 

//custom panel 
class ShapePanel extends JPanel { 

    private Shape rect = new Rectangle2D.Double(50, 100, 200, 100); 
    private Shape cirlce = new Ellipse2D.Double(260, 100, 100, 100); 
    private Dimension dim = new Dimension(450, 300); 
    private final ArrayList<Shape> shapes; 

    public ShapePanel() { 
     shapes = new ArrayList<>(); 
     shapes.add(rect); 
     shapes.add(cirlce); 
     addMouseListener(new MouseAdapter() { 
      @Override 
      public void mouseClicked(MouseEvent me) { 
       super.mouseClicked(me); 
       for (Shape s : shapes) { 

        if (s.contains(me.getPoint())) {//check if mouse is clicked within shape 

         //we can either just print out the object class name 
         System.out.println("Clicked a "+s.getClass().getName()); 

         //or check the shape class we are dealing with using instance of with nested if 
         if (s instanceof Rectangle2D) { 
          System.out.println("Clicked a rectangle"); 
         } else if (s instanceof Ellipse2D) { 
          System.out.println("Clicked a circle"); 
         } 

        } 
       } 
      } 
     }); 
    } 

    @Override 
    protected void paintComponent(Graphics grphcs) { 
     super.paintComponent(grphcs); 
     Graphics2D g2d = (Graphics2D) grphcs; 
     for (Shape s : shapes) { 
      g2d.draw(s); 
     } 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return dim; 
    } 
} 
+2

To nie rozwiązało problemu, ale bardzo doceniam wysiłek. Dzięki :) –

3

Jeśli wdrażasz Shape, musisz samodzielnie wdrożyć metodę contains. Domyślna implementacja dla Shape zawsze zwraca false.

Jeśli twój Shape jest ograniczony przez krzywe, które znasz, jak przecinać (lub określić, czy punkt znajduje się po jednej lub drugiej stronie), możesz użyć even-odd rule. Rzuć promień od punktu testowanego w dowolnym kierunku, nierównoległym do linii prostej. Jeśli liczba skrzyżowań jest nieparzysta, punkt znajduje się w środku. Jeśli liczba skrzyżowań jest równa, punkt znajduje się na zewnątrz.

Wbudowane klasy implementują tę metodę, dzięki czemu można używać/rozszerzenie klasy Polygon, Ellipse2D.Double lub RoundRectangle2D.Double i mają wypełniony wielokąt/elipsy/okrągły prostokąt, który zna jego środku.

+0

Dzięki za odpowiedź. Ponieważ moje klasy kształtów nazywają metodę rysowania i rysują taki kształt, nie są tak naprawdę związane klasą kształtu, czy są? –

+0

@DotNET powiedziałeś, że masz 'shapeArrayList'? Tak więc metoda, którą wypróbowałeś, zadziała, jeśli zaimplementujesz metodę "zawiera". –

+0

Zrozumiałem, że bardzo dziękuję. Nie jestem jednak pewien, jak zaimplementować metodę zawiera. To ma być bardzo proste zadanie obejmujące podstawy java, jednak to, o czym wspomniałeś, wydaje się być złożone poza zakres tego zadania. –

Powiązane problemy