Java命中测试行为异常

Java命中测试行为异常,java,swing,geometry,hittest,Java,Swing,Geometry,Hittest,我试图扩展JavaScrollDemo2以报告画布上的形状是否被单击。我从一个简单的矩形开始,认为在画布中简单地在矩形上循环检查单击点是否包含在其中应该没有问题。但是后来发生了一些奇怪的事情,contains方法似乎只关心点是否位于锚定在(0,0)的矩形中,而不关心我的组件是否位于y=20。因此,如果我从x:[0,20]y:[0,20]点击Jpanel,我会得到一个点击,而只有当我点击x:[0,20]y[20,40]时,我才应该得到一个点击。这是一个bug,还是我做错了什么 public cla

我试图扩展JavaScrollDemo2以报告画布上的形状是否被单击。我从一个简单的矩形开始,认为在画布中简单地在矩形上循环检查单击点是否包含在其中应该没有问题。但是后来发生了一些奇怪的事情,contains方法似乎只关心点是否位于锚定在(0,0)的矩形中,而不关心我的组件是否位于y=20。因此,如果我从x:[0,20]y:[0,20]点击Jpanel,我会得到一个点击,而只有当我点击x:[0,20]y[20,40]时,我才应该得到一个点击。这是一个bug,还是我做错了什么

public class CachedDrawableComponent extends JComponent
{
//this will do more later
    CachedDrawableComponent(Rectangle bounds)
    {
        this.setBounds(bounds);
    }
    protected void paintComponent(Graphics g)
    {
        g.setColor(Color.magenta);
        Rectangle r = this.getBounds();
        g.fillRect(r.x, r.y, r.width, r.height);
    }

}

public class ScrollDemo2 extends JPanel
                         implements MouseListener {
    private Dimension area; //indicates area taken up by graphics
    private Vector<Rectangle> circles; //coordinates used to draw graphics
    private Vector<CachedDrawableComponent> otherDrawables;
    private JPanel drawingPane;

    private final Color colors[] = {
        Color.red, Color.blue, Color.green, Color.orange,
        Color.cyan, Color.magenta, Color.darkGray, Color.yellow};
    private final int color_n = colors.length;

    public ScrollDemo2() {
        super(new BorderLayout());

        area = new Dimension(0,0);
        circles = new Vector<Rectangle>();
        this.otherDrawables = new Vector<CachedDrawableComponent>();

        //Set up the instructions.
        JLabel instructionsLeft = new JLabel(
                        "Click left mouse button to place a circle.");
        JLabel instructionsRight = new JLabel(
                        "Click right mouse button to clear drawing area.");
        JPanel instructionPanel = new JPanel(new GridLayout(0,1));
        instructionPanel.setFocusable(true);
        instructionPanel.add(instructionsLeft);
        instructionPanel.add(instructionsRight);

        //Set up the drawing area.
        drawingPane = new DrawingPane();
        drawingPane.setBackground(Color.white);
        drawingPane.addMouseListener(this);
        TestRect t = new TestRect(new Rectangle(0,20,20,20));
        this.otherDrawables.add(t); 


        //Put the drawing area in a scroll pane.
        JScrollPane scroller = new JScrollPane(drawingPane);
        scroller.setPreferredSize(new Dimension(200,200));

        //Lay out this demo.
        add(instructionPanel, BorderLayout.PAGE_START);
        add(scroller, BorderLayout.CENTER);
    }

    /** The component inside the scroll pane. */
    public class DrawingPane extends JPanel {
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Rectangle rect;
            for (int i = 0; i < circles.size(); i++) {
                rect = circles.elementAt(i);
                g.setColor(colors[(i % color_n)]);
                g.fillOval(rect.x, rect.y, rect.width, rect.height);

            }

            for (int i = 0; i < otherDrawables.size(); i++) {
                CachedDrawableComponent drawMe = otherDrawables.elementAt(i);;
                g.setColor(colors[(i % color_n)]);
                drawMe.paint(g);

            }
        }
    }

    //Handle mouse events.
    public void mouseReleased(MouseEvent e) {
        final int W = 100;
        final int H = 100;
        boolean changed = false;
        if (SwingUtilities.isRightMouseButton(e)) {
            //This will clear the graphic objects.
            circles.removeAllElements();
            area.width=0;
            area.height=0;
            changed = true;
        } else {
            int x = e.getX() - W/2;
            int y = e.getY() - H/2;
            if (x < 0) x = 0;
            if (y < 0) y = 0;
            Rectangle rect = new Rectangle(x, y, W, H);
            circles.addElement(rect);
            drawingPane.scrollRectToVisible(rect);

            int this_width = (x + W + 2);
            if (this_width > area.width) {
                area.width = this_width; changed=true;
            }

            int this_height = (y + H + 2);
            if (this_height > area.height) {
                area.height = this_height; changed=true;
            }
        }
        if (changed) {
            //Update client's preferred size because
            //the area taken up by the graphics has
            //gotten larger or smaller (if cleared).
            drawingPane.setPreferredSize(area);

            //Let the scroll pane know to update itself
            //and its scrollbars.
            drawingPane.revalidate();
        }
        drawingPane.repaint();
    }
    public void mouseClicked(MouseEvent e){}
    public void mouseEntered(MouseEvent e){}
    public void mouseExited(MouseEvent e){}
    public void mousePressed(MouseEvent e)
    {
        System.out.println("Did press:"+e.getPoint());
        System.out.println(otherDrawables.get(0).getBounds());
        if(otherDrawables.get(0).contains(e.getPoint()))
        {
            System.out.println("Did Hit");
        }

    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("ScrollDemo2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        JComponent newContentPane = new ScrollDemo2();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}



Output:

    Did press:java.awt.Point[x=8,y=7]
    java.awt.Rectangle[x=0,y=20,width=20,height=20]
    Did Hit
    Did press:java.awt.Point[x=14,y=89]
    java.awt.Rectangle[x=0,y=20,width=20,height=20]
public类CachedDrawableComponent扩展JComponent
{
//这将在以后做得更多
CachedDrawableComponent(矩形边界)
{
这个。挫折(界限);
}
受保护组件(图形g)
{
g、 setColor(颜色为洋红色);
矩形r=this.getBounds();
g、 fillRect(r.x,r.y,r.宽度,r.高度);
}
}
公共类ScrollDemo2扩展了JPanel
鼠标听器{
私有维度区域;//表示图形占用的区域
专用矢量圆;//用于绘制图形的坐标
可提取的私有向量;
私人JPanel绘图窗格;
专用最终颜色[]={
颜色。红色,颜色。蓝色,颜色。绿色,颜色。橙色,
Color.cyan,Color.洋红,Color.darkGray,Color.yellow};
私有最终int color\u n=colors.length;
公共文件2(){
超级(新边框布局());
面积=新尺寸(0,0);
圆=新向量();
this.otherDrawables=新向量();
//设置说明。
JLabel指令左=新JLabel(
“单击鼠标左键放置一个圆。”);
JLabel指令右侧=新JLabel(
“单击鼠标右键以清除绘图区域。”);
JPanel指令面板=新JPanel(新网格布局(0,1));
说明面板。设置聚焦(真);
说明面板。添加(说明左侧);
说明面板。添加(说明右侧);
//设置绘图区域。
drawingPane=新的drawingPane();
绘图窗格。背景(颜色。白色);
drawingPane.addMouseListener(此);
TestRect t=newtestrect(新矩形(0,20,20,20));
此.其他可提取项.添加(t);
//将绘图区域置于滚动窗格中。
JScrollPane scroller=新的JScrollPane(drawingPane);
scroller.setPreferredSize(新维度(200200));
//展示这个演示。
添加(说明面板,边框布局。页面开始);
添加(滚动条,BorderLayout.CENTER);
}
/**滚动窗格中的组件*/
公共类DrawingPane扩展了JPanel{
受保护组件(图形g){
超级组件(g);
矩形矩形;
对于(int i=0;i面积宽度){
area.width=此宽度;changed=真;
}
int此_高度=(y+H+2);
如果(此高度>面积高度){
area.height=此高度;changed=真;
}
}
如果(更改){
//更新客户端的首选大小,因为
//图形占用的区域已被删除
//变大或变小(如果清除)。
drawingPane.setPreferredSize(面积);
//让滚动窗格知道如何更新自身
//还有它的滚动条。
drawingPane.revalidate();
}
drawingPane.repaint();
}
公共无效mouseClicked(MouseEvent e){}
公共无效mouseenterned(MouseEvent e){}
公共无效mouseExited(MouseEvent e){}
公共无效鼠标按下(MouseEvent e)
{
System.out.println(“按:+e.getPoint());
System.out.println(otherDrawables.get(0.getBounds());
if(otherDrawables.get(0).contains(e.getPoint()))
{
System.out.println(“命中”);
}
}
/**
*创建GUI并显示它。为了线程安全,
*应该从
*事件调度线程。
*/
私有静态void createAndShowGUI(){
//创建并设置窗口。
JFrame=新的JFrame(“ScrollDemo2”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//创建并设置内容窗格。
JComponent newContentPane=new ScrollDemo2();
newContentPane.setOkable(true);//内容窗格必须是不透明的
frame.setContentPane(newContentPane);
//显示窗口。
frame.pack();
frame.setVisible(true);
}
公共静态void main(字符串[])