2012-10-17 37 views
5

Tôi có một lớp được gọi là Shape được kế thừa từ JPanel.Nhấp vào một đối tượng được vẽ

Một số phân lớp lần lượt mở rộng các lớp Shape, một cho mỗi loại hình dạng.

Mỗi hình có phương pháp paint() được ghi đè riêng của nó, vẽ hình dạng tương ứng.

Tôi muốn có thể nhấp vào bất kỳ hình dạng nào và hiện đang cố triển khai logic này. Xin lưu ý rằng mỗi hình dạng đã được thêm vào một arrayList.

Tuy nhiên, câu lệnh chứa luôn trả về false, ngay cả khi tôi đã nhấp rõ ràng bên trong hình dạng.

Bất kỳ ý tưởng nào?

+0

OK, được bạn lên kế hoạch cho một cái gì đó giống như thành phần hình dạng sơn? – Takarakaka

+0

Loại hình nào? Bạn phải thực hiện phương thức 'contains'. Nó sẽ không tự tạo ra từ phương pháp 'sơn' của họ. –

+0

Bạn có thể vui lòng xây dựng xin vui lòng @JanDvorak? Cho đến nay chương trình hoạt động, theo đó một số hình dạng được vẽ trên màn hình. Vấn đề của tôi là tôi dường như không thể bấm vào bất kỳ hình dạng nào. –

Trả lời

10

Không bao giờ ghi đè paint() trong JPanel thay paintComponent(..)

Im không hoàn toàn chắc là tôi hiểu tuy nhiên tôi đã thực hiện một ví dụ ngắn mà tôi hy vọng sẽ giúp đỡ. Về cơ bản nó là một đơn giản JFrame với một DrawingPanel (lớp của riêng tôi mở rộng JPanel và các hình dạng được vẽ trên). Bảng điều khiển này sẽ tạo hình dạng (chỉ 2 cho thử nghiệm) thêm chúng vào ArrayList và vẽ chúng vào JPanel qua paintComponent(..) và vòng lặp for, nó cũng có MouseAdapter để kiểm tra người dùng mouseClicked(..) evnets trên JPanel. Khi nhấp chuột được làm chúng ta lặp qua từng Shape trong ArrayList và kiểm tra xem Shape chứa các điểm hay không, và nếu có thì in tên lớp của nó và sử dụng instance of để kiểm tra những gì loại Shape được nhấp và in thông điệp thích hợp:

enter image description here

Output (sau khi nhấp vào cả hình dạng):

Clicked một java.awt.geom.Rectangle2D $ đúp

Đã nhấp vào hình chữ nhật

Nhấp vào một java.awt.geom.Ellipse2D $ đúp

Clicked một vòng tròn

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

Nó không giải quyết được vấn đề tuy nhiên tôi đánh giá cao nỗ lực này. Cảm ơn :) –

3

Nếu bạn đang thực hiện Shape, bạn phải tự mình thực hiện phương thức contains. Việc triển khai mặc định cho Shape luôn trả về false.

Nếu Shape của bạn bị ràng buộc bởi các đường cong mà bạn biết cách giao nhau (hoặc xác định xem một điểm ở một bên hay phía bên kia), bạn có thể sử dụng even-odd rule. Đúc một tia từ điểm được kiểm tra theo bất kỳ hướng nào không song song với đường thẳng. Nếu số lượng nút giao là lẻ, điểm nằm bên trong. Nếu số lượng giao lộ là ngay cả, điểm ở bên ngoài.

Các lớp dựng sẵn thực hiện phương pháp này, vì vậy bạn có thể sử dụng/mở rộng lớp Polygon, Ellipse2D.Double hoặc RoundRectangle2D.Double và có hình chữ nhật đa giác/hình elip/hình tròn biết bên trong.

+0

Cảm ơn bạn đã trả lời. Vì các lớp hình dạng của tôi gọi phương thức vẽ và vẽ một hình dạng như vậy, chúng không thực sự bị ràng buộc với lớp hình dạng là chúng? –

+0

@DotNET bạn đã nói bạn có một 'shapeArrayList'? Vì vậy, phương pháp bạn đã thử sẽ hoạt động nếu bạn thực hiện phương thức 'contains'. –

+0

Tôi đã hiểu rằng cảm ơn rất nhiều. Tôi không chắc chắn về cách thực hiện phương pháp chứa mặc dù. Điều này được coi là một nhiệm vụ rất đơn giản bao gồm những điều cơ bản của java, tuy nhiên những gì bạn đề cập có vẻ phức tạp vượt ra ngoài phạm vi của nhiệm vụ này. –

Các vấn đề liên quan