2013-02-17 5 views
0

내 JComponent에 MouseListener를 추가하려고합니다. 난 원 (JComponent의 페인팅 메소드가 원을 그리는) 경계를 누르고있을 때 MouseListener가 트리거되기를 원한다. 나는 아래의 코드로 시도했지만 나는 그것을 작동시키지 못한다 (특히 mousePressed 메서드에서 loook). 이 문제를 어떻게 해결할 수 있습니까?내 JComponent가 AffineTransform에 의해 변형 되어도, 트리거 할 때 MouseListener를 트리거

SSCCE :

import java.awt.*; 
import java.awt.event.*; 
import java.awt.geom.AffineTransform; 
import java.awt.geom.Rectangle2D; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 

public class AffineTransformTest { 

    private static TransformingCanvas canvas; 

    public static void main(String[] args) { 
     JFrame frame = new JFrame(); 
     canvas = new AffineTransformTest.TransformingCanvas(); 
     TranslateHandler translater = new TranslateHandler(); 
     canvas.addMouseListener(translater); 
     canvas.addMouseMotionListener(translater); 
     canvas.addMouseWheelListener(new ScaleHandler()); 
     frame.setLayout(new BorderLayout()); 
     frame.getContentPane().add(canvas, BorderLayout.CENTER); 
     frame.setSize(500, 500); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.setVisible(true); 
    } 

    private static class TransformingCanvas extends JComponent { 

     private double translateX; 
     private double translateY; 
     private double scale; 

     TransformingCanvas() { 
      translateX = 0; 
      translateY = 0; 
      scale = 1; 
      setOpaque(true); 
      setDoubleBuffered(true); 
     } 

     @Override 
     public void paint(Graphics g) { 

      AffineTransform tx = new AffineTransform(); 
      tx.translate(translateX, translateY); 
      tx.scale(scale, scale); 
      Graphics2D ourGraphics = (Graphics2D) g; 
      ourGraphics.setColor(Color.WHITE); 
      ourGraphics.fillRect(0, 0, getWidth(), getHeight()); 
      ourGraphics.setTransform(tx); 
      ourGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
        RenderingHints.VALUE_ANTIALIAS_ON); 
      ourGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 
        RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 
      ourGraphics.setColor(Color.BLACK); 
      ourGraphics.fillOval(50, 50, 50, 50); 
     } 
    } 

    private static class TranslateHandler implements MouseListener, 
      MouseMotionListener { 

     private int lastOffsetX; 
     private int lastOffsetY; 

     public void mousePressed(MouseEvent e) { 
      lastOffsetX = e.getX(); 
      lastOffsetY = e.getY(); 

      double width = canvas.scale * 50; 
      double height = canvas.scale * 50; 
      double x = (AffineTransformTest.canvas.getWidth() - width)/2; 
      double y = (AffineTransformTest.canvas.getHeight() - height)/2; 
      Rectangle2D.Double bounds = new Rectangle2D.Double(x, y, width, height); 
      System.out.println(bounds + " " + e.getPoint()); 
      if (bounds.contains(e.getPoint())) { 
       System.out.println("Click!"); 
      } 
     } 

     public void mouseDragged(MouseEvent e) { 
      int newX = e.getX() - lastOffsetX; 
      int newY = e.getY() - lastOffsetY; 

      lastOffsetX += newX; 
      lastOffsetY += newY; 

      canvas.translateX += newX; 
      canvas.translateY += newY; 

      canvas.repaint(); 
     } 

     public void mouseClicked(MouseEvent e) { 
     } 

     public void mouseEntered(MouseEvent e) { 
     } 

     public void mouseExited(MouseEvent e) { 
     } 

     public void mouseMoved(MouseEvent e) { 
     } 

     public void mouseReleased(MouseEvent e) { 
     } 
    } 

    private static class ScaleHandler implements MouseWheelListener { 

     public void mouseWheelMoved(MouseWheelEvent e) { 
      if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) { 
       canvas.scale += (.1 * e.getWheelRotation()); 
       canvas.scale = Math.max(0.00001, canvas.scale); 
       canvas.repaint(); 
      } 
     } 
    } 
} 
+0

특정 상황에 대해 'JComponent'보다'JButton '을 확장하는 것이 더 낫습니다. & BTW는 * "작동하지 못합니다"라고하는 것이 무엇입니까? * –

+0

어쩌면하지만 이것은 단지 SSCCE입니다. 내 실제 코드는 훨씬 크고 JComponent에서 파생 된 사용자 정의 구성 요소를 사용하므로이 코드가 실제 문제와 더 잘 어울릴 것이라고 생각했습니다. – Rox

+0

확대/축소 할 때 작동하지 않는 것은 무엇입니까? 확대 또는 축소했을 때 마우스 조작은 페인트 된 객체의 범위 내에있을 수 없습니다. – Rox

답변

0

두 지점 :

첫째, 나는 모양 또는 영역 객체를 사용하고 .contains() 메소드를 사용합니다. Bounds는 항상 전체 모양을 둘러싼 사각형입니다. 또한, JComponent의 setBounds() 메소드를 사용할 수있는 경우 경계 사각형을 만드는 이유를 모르겠습니다.

둘째, JComponent의 경계를 변환 할 수 있지만 확장을 위해 내장 된 항목을 찾지 못했습니다. 그러나 크기를 동적으로 변경할 수 있습니다. 나는 동일한 문제에 대해 연구하고있다. 지금은 JComponent의 크기가 변할 때 경계를 동적으로 변경하는 것을 고려하고 있습니다. 화면 좌표와 JComponent 좌표 간의 상관 관계를 이해하려고합니다. 마우스 좌표는 항상 스케일링되지 않은 프레임/화면 좌표에있는 것처럼 보입니다. (내가 사용하고있는 전체 화면 모드의 아티팩트 일 수 있습니다. 내가 본 솔루션은 JPanel에서 모든 것을 페인트하고 이산 JComponents를 사용하여 크기 조정 문제를 해결하지 않습니다. 코드는 따라하기가 조금 어렵지만 특별히 모듈화 된 것은 아니지만 작동하지 않습니다.

어쨌든 나는 궁극적으로 그것을 수행 할 수 있다고 확신합니다. 확장 기능이있는 JComponent 확장을위한 코드는 안정적으로 작동합니다. 희망이 조금 있습니다.

+0

자, JComponent를 확장 한 추상 클래스의 코드를 보자.이 클래스는 컴포넌트를 확장 및 변환하고 계속 신뢰할 수있게 해준다. 아직 완료되지 않았지만 JComponent를 확장하고 확장 가능하고 클릭 할 수있는 방법을 보여줍니다. extend를 사용하고 Extension이 Area 객체를 만들도록하십시오. 내가 임의로 확장 할 수 있도록 만들지는 않았다. 그것은 내 요구 사항이었던 화면 크기에 따라 확장됩니다. –

0

코드가 있습니다. 몇 가지 간단한 메모, 여전히 코드에서 일부 디버그 및 LOGGER 개체 System.out.println().

import java.awt.Color; 
import java.awt.Container; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.RenderingHints; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseEvent; 
import java.awt.geom.AffineTransform; 
import java.awt.geom.Area; 
import java.awt.geom.Point2D; 
import java.util.logging.Logger; 

import javax.swing.JComponent; 
import javax.swing.event.MouseInputListener; 


public abstract class LCARSComponent extends JComponent implements MouseInputListener { 

/** 
* A reference to the global Logger object. 
*/ 
protected final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); 

protected int x; 
protected int y; 
protected int w; 
protected int h; 

protected double scaleFactor = 1.0; 

protected Area area; 
protected Area scaledArea; 
protected int style; 

protected Color color; 

protected AffineTransform renderingTransform; 

protected ActionListener actionListener; 

public LCARSComponent(Container parent, int x, int y, int w, int h, int style) { 

    this.x = x; 
    this.y = y; 
    this.w = w; 
    this.h = h; 

    this.style = style; 

    setBounds(x,y,w,h); 

    addMouseListener(this); 

} 


@Override 
protected void paintComponent(Graphics g) { 

    /** 
    * First, paint the background if the component is opaque. Required when 
    * JComponent is extended, and the paintCompnent() method is overridden. 
    */ 
    if(isOpaque()) { 
     g.setColor(getBackground()); 
     g.fillRect(0, 0, getWidth(), getHeight()); 
    } 

    /** 
    * Create a Graphics2D object so we can use Java 2D features. 
    */ 
    Graphics2D g2d = (Graphics2D) g.create(); 

    /** 
    * Set the anti aliasing rendering hint and the color to draw with. 
    */ 
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
    g2d.setColor(color); 


    scaleComponent();  

    /** 
    * Draw the Area object of the LCARS component, and fill it. 
    */ 
    g2d.draw(scaledArea); 
    g2d.fill(scaledArea); 

    g2d.drawRect(scaledArea.getBounds().x, scaledArea.getBounds().y, scaledArea.getBounds().width, scaledArea.getBounds().height); 

    /** 
    * Clean up when the method has completed by disposing the Graphics2D object that was created. 
    */ 
    g2d.dispose(); 

} 


protected void scaleComponent() { 
    double sw = (double)getParent().getWidth()/(double)getParent().getPreferredSize().width; 
    double sh = (double)getParent().getHeight()/(double)getParent().getPreferredSize().height; 

    LOGGER.info("scaledWidth = " + sw); 
    LOGGER.info("scaledHeight = " + sh); 

    double scaleFactor; 

    if(sh < sw) { 
     scaleFactor = sh; 
    } 
    else { 
     scaleFactor = sw; 
    } 

    LOGGER.info("scaleFactor = " + scaleFactor); 

    if(scaleFactor != this.scaleFactor) { 
     this.scaleFactor = scaleFactor; 

     scaledArea = new Area(area); 
     renderingTransform = new AffineTransform(); 
     renderingTransform.scale(scaleFactor, scaleFactor); 
     scaledArea.transform(renderingTransform);   
    } 

    setBounds((int)(this.x*scaleFactor), (int)(this.y*scaleFactor), this.getWidth(), this.getHeight()); 
} 


public Point screenToComponent(Point pt) { 

    if(renderingTransform == null) { 
     Graphics2D g2d = (Graphics2D)(this.getParent().getGraphics()); 
     renderingTransform = g2d.getTransform();    
    } 


    Point2D pt2d = renderingTransform.transform(pt,null); 

    LOGGER.info("mouse click: " + pt.getX() + ", " + pt.getY() + " -- " + pt2d.getX() + ", " + pt2d.getY()); 
    return new Point((int)Math.round(pt2d.getX()), (int)Math.round(pt2d.getY())); 
} 


public void setActionListener(ActionListener actionListener) { 
    this.actionListener = actionListener; 
} 


@Override 
public void mouseClicked(MouseEvent e) { 

    Point pt = e.getPoint(); 
    LOGGER.info("mouseClicked: " + this.getName() + " - " + pt.getX() + ", " + pt.getY()); 

    if(area.contains(e.getPoint())) { 

     if(actionListener != null) { 
      actionListener.actionPerformed(new ActionEvent(e.getSource(), e.getID(), e.paramString())); 
     } 

     if(color.equals(Color.black)) 
      color = Color.blue; 
     else 
      color = Color.black; 
     this.repaint(); 
    } 
} 

@Override 
public void mousePressed(MouseEvent e) { 
    // TODO Auto-generated method stub 
    if(area.contains(e.getLocationOnScreen())) 
     System.out.println("mousePressed()..."); 
} 

@Override 
public void mouseReleased(MouseEvent e) { 
    // TODO Auto-generated method stub 
    if(area.contains(e.getLocationOnScreen())) 
     System.out.println("mouseReleased()..."); 
} 

@Override 
public void mouseEntered(MouseEvent e) { 
    Point pt = e.getPoint(); 
    // TODO Auto-generated method stub 
    System.out.println("mouseEntered()..."); 
    LOGGER.info("mouseEntered: " + this.getName() + " - " + pt.getX() + ", " + pt.getY()); 

} 

@Override 
public void mouseExited(MouseEvent e) { 
    // TODO Auto-generated method stub 
    Point pt = e.getPoint(); 
    System.out.println("mouseExited()..."); 
    LOGGER.info("mouseExited: " + pt.getX() + ", " + pt.getY()); 
} 

@Override 
public void mouseDragged(MouseEvent e) { 
    // TODO Auto-generated method stub 
    System.out.println("mouseDragged()..."); 
} 

@Override 
public void mouseMoved(MouseEvent e) { 
    // TODO Auto-generated method stub 
    System.out.println("mouseMoved()..."); 
} 
}