2017-02-02 80 views
0

簡單的問題之一:的Java Swing Rectangel2D:如何選擇頂部

我繪製多個Rectangel2D(或其他形狀)在一個JPane與重疊。 我想通過點擊重疊區域來選擇頂部的一個,並執行一些操作,例如改變顏色或拖動。

但我不能選擇我想要的。

形狀的順序不受控制。

我找到了一個方法setComponentZOrder,但是這個組件不適用於Rectangel2D。

我認爲這是一個典型的問題,但我找不到答案。

+0

歡迎棧溢出,請參加[遊覽]並通過[幫助],然後學習[問],一旦你這樣做,回來一個適當的[mcve]或[短,自包含,正確的例子](http: //sscce.org/),這證明了你的問題。 – Frakcool

回答

3

繪製諸如Rectangle2D之類的Shape的順序取決於它們保存在任何集合中的順序,因爲此集合在您的JComponent(例如JPanel)繪畫方法中迭代。因此,集合中的最後一項,無論是數組還是ArrayList或LinkedList,都在頂部上繪製。

所以,如果你想獲得上按下鼠標頂部的形狀或點擊,那麼關鍵是通過相同的集合向後迭代,獲得該contains(Point p)鼠標點位置的第一個形狀。而已。

例如,請看看我的代碼here這不只是他在這個方法中從MouseListener的(實際上MouseAdapater)呼籲:

public Shape getShapeAtPoint(Point p) { 
    Shape shapeAtPoint = null; 
    for (int i = shapeList.size() - 1; i >= 0; i--) { 
     if (shapeList.get(i).contains(p)) { 
      return shapeList.get(i); 
     } 
    } 
    return shapeAtPoint; 
} 

例如:

import java.awt.BasicStroke; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.RenderingHints; 
import java.awt.Shape; 
import java.awt.Stroke; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.geom.AffineTransform; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Path2D; 
import java.awt.geom.Rectangle2D; 
import java.awt.geom.RoundRectangle2D; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Random; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class RandomShapes extends JPanel { 
    private static final Stroke STROKE = new BasicStroke(4f); 
    private static final int PREF_W = 800; 
    private static final int PREF_H = 650; 
    private static final int SHAPE_COUNT = 30; 
    private static final int SHAPE_WIDTH = 100; 
    private static final int SHAPE_HEIGHT = SHAPE_WIDTH; 
    private List<Path2D> paths = new ArrayList<>(); 
    private Map<Path2D, Color> colorMap = new HashMap<>(); 
    private Random random = new Random(); 

    public RandomShapes() { 
     for (int i = 0; i < SHAPE_COUNT; i++) { 
      Shape shape = createRandomShape(i); 
      Path2D path = new Path2D.Double(shape); 
      paths.add(path); 
      colorMap.put(path, createRandomColor()); 
     } 
     MyMouse myMouse = new MyMouse(); 
     addMouseListener(myMouse); 
     addMouseMotionListener(myMouse); 
    } 

    private class MyMouse extends MouseAdapter { 
     private Path2D selectedPath = null; 
     private Point p1; 

     @Override 
     public void mousePressed(MouseEvent e) { 
      if (e.getButton() != MouseEvent.BUTTON1) { 
       return; 
      } 
      for (int i = paths.size() - 1; i >= 0; i--) { 
       Path2D path = paths.get(i); 
       if (path.contains(e.getPoint())) { 
        selectedPath = path; 
        p1 = e.getPoint(); 
        paths.remove(selectedPath); 
        paths.add(selectedPath); 
        repaint(); 
        break; 
       } 
      } 
     } 

     private void movePath(MouseEvent e) { 
      Point p2 = e.getPoint(); 
      int tx = p2.x - p1.x; 
      int ty = p2.y - p1.y; 
      p1 = p2; 
      AffineTransform at = AffineTransform.getTranslateInstance(tx, ty); 
      selectedPath.transform(at); 
      repaint(); 
     } 

     @Override 
     public void mouseDragged(MouseEvent e) { 
      if (selectedPath != null) { 
       movePath(e); 
      } 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
      if (selectedPath != null) { 
       movePath(e); 
      } 
      selectedPath = null; 
     } 
    } 

    private Color createRandomColor() { 
     float min = 0.2f; 
     float h = random.nextFloat(); 
     float s = min * random.nextFloat() + (1f - min); 
     float b = min * random.nextFloat() + (1f - min); 
     return Color.getHSBColor(h, s, b); 
    } 

    private Shape createRandomShape(int i) { 
     Dimension size = getPreferredSize(); 
     int x = random.nextInt(size.width - SHAPE_WIDTH); 
     int y = random.nextInt(size.height - SHAPE_HEIGHT); 
     switch (i % 3) { 
     case 0: 
      return new Ellipse2D.Double(x, y, SHAPE_WIDTH, SHAPE_HEIGHT); 
     case 1: 
      return new Rectangle2D.Double(x, y, SHAPE_WIDTH, SHAPE_HEIGHT); 
     case 2: 
      return new RoundRectangle2D.Double(x, y, SHAPE_WIDTH, SHAPE_HEIGHT, 15, 15); 
     default: 
      break; 
     } 
     return null; 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     g2.setStroke(STROKE); 
     for (Path2D path : paths) { 
      g2.setColor(colorMap.get(path)); 
      g2.fill(path); 
      g2.setColor(colorMap.get(path).darker()); 
      g2.draw(path); 
     } 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("RandomShapes"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new RandomShapes()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
}