2012-10-17 16 views
5

Ho una classe chiamata Shape che eredita da JPanel.Cliccando su un oggetto disegnato

Un numero di sottoclassi a sua volta estendono le classi Shape, una per ogni tipo di forma.

Ogni forma ha il proprio metodo annullato paint(), che disegna la rispettiva forma.

Vorrei poter fare clic su qualsiasi forma e sto cercando di implementare questa logica per ora. Si noti che ogni forma è stata aggiunta a una lista di array.

Tuttavia, l'istruzione contiene restituisce sempre false, anche quando ho fatto clic con chiarezza all'interno della forma.

Qualche idea?

+0

OK, avete in programma qualcosa come componente forme di vernice? – Takarakaka

+0

Che tipo di forme? Devi implementare il metodo 'contains'. Non si genererà dal loro metodo "vernice". –

+0

Potrebbe gentilmente elaborare per favore @ Jan Dvorak? Finora il programma funziona, per cui un numero di forme sono disegnate sullo schermo. Il mio problema è che non riesco a cliccare su nessuna delle forme. –

risposta

10

Non escludere paint() in JPanel piuttosto paintComponent(..)

Im non del tutto sicuro di aver capito però ho fatto un breve esempio che spero vi aiuterà. Fondamentalmente è un semplice JFrame con un DrawingPanel (la mia classe che estende JPanel e le forme sono disegnate). Questo pannello creerà le forme (solo 2 per il test) aggiungerle a un ArrayList e disegnarle allo JPanel tramite paintComponent(..) e un ciclo for, ma ha anche un MouseAdapter per verificare gli utenti mouseClicked(..) su JPanel. Quando un clic è fatto iteriamo attraverso ogni Shape nel ArrayList e verificare se il Shape contiene il punto o no, e se sì stampa il nome della classe e utilizza instance of per verificare che tipo di Shape viene cliccato e stampe messaggio appropriato:

enter image description here

uscita (dopo aver cliccato su entrambe le forme):

fatto clic su un java.awt.geom.Rectangle2D $ doppio

Cliccato su un rettangolo

Cliccato su java.awt.geom.Ellipse2D $ Doppio

fatto clic su un cerchio

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

Non ha risolto il problema, tuttavia apprezzo molto lo sforzo. Grazie :) –

3

Se si sta implementando Shape, è necessario implementare il metodo contains. L'implementazione predefinita per Shape restituisce sempre false.

Se il tuo Shape è limitato da curve che sai come intersecare (o determinare se un punto si trova su uno o l'altro lato), puoi usare lo even-odd rule. Cast un raggio dal punto testato in qualsiasi direzione non parallela a una linea retta. Se il numero di intersezioni è dispari, il punto è all'interno. Se il numero di intersezioni è pari, il punto è all'esterno.

Le classi incorporate implementare questo metodo, in modo da poter utilizzare/estendere la classe Polygon, Ellipse2D.Double o RoundRectangle2D.Double e hanno un poligono/un'ellisse/rettangolo arrotondato pieno che conosce suo interno.

+0

Grazie per la risposta. Dal momento che le mie classi di forme chiamano il metodo draw e disegnano una forma del genere, non sono realmente legate alla classe della forma, vero? –

+0

@DotNET hai detto di avere un 'shapeArrayList'? Quindi, il metodo che hai provato funzionerà se implementerai il metodo 'contains'. –

+0

Ho capito molto grazie. Non sono però così sicuro su come implementare il metodo contiene. Questo dovrebbe essere un compito molto semplice che copre le basi di Java, tuttavia ciò che hai menzionato sembra complesso oltre lo scopo di questo compito. –

Problemi correlati