如何使点击区域只是图像非矩形部分的一部分?

时间:2012-11-22 06:28:49

标签: java image mouseevent rectangles

我正在处理图像,我用来查看我的应用程序的窗口的尺寸可能在不同的系统上有所不同。我有一个鼠标动作监听器,它正在监听我程序主视图的点击。我有一个看起来像按钮的圆角矩形。我想这样做,鼠标动作监听器只能监听圆角矩形的区域而不是所有系统上的整个图像。就像标题所说,并非整个图像都有内容,特别是角落看起来不像是图像的一部分,所以我不想让用户能够点击图像的某些部分而不用内容并获得相同的结果,就好像他们点击了包含内容的部分一样。 我的图片与此image http://www.youthedesigner.com/wp-content/uploads/2011/02/gimp-tutorial-on-creating-buttons-421.png类似 因此,如果用户单击图像内的按钮而不是按钮周围的好东西,我只希望程序执行某些操作。 这就是我现在听取点击的内容:

@Override
public void mouseClicked(MouseEvent e) {
    for(int i = 0; i <= 200; i++) {
        if(e.getY() >= 100+i && e.getY() <= 300) {
            if(e.getX() >= 10+100-Math.pow(10000-(Math.pow((i-100),2.0)),.5)) && e.getX() <= 10+400-Math.pow(10000-(Math.pow((i-100),2.0)),.5))) {
                // do stuff
                i = 201;
            }
        }
    }
}

我在我的代码中使用的数学公式看起来像110-(10000-(y-100)^ 2)^(1/2)),如果绘制的话,看起来像一个开括号,410 + (10000-(y-100)^ 2)^(1/2)),看起来像是距离第一张图400个单位的近括号。

代码在我的系统上工作正常,但在其他系统上,它根本不起作用,我很好奇我如何移动我正在听的位置以对应图像的缩放方式。

非常感谢您提供的任何帮助。

3 个答案:

答案 0 :(得分:1)

for循环是多余的。

您可以确保按钮(.png)外的像素具有一定的透明度,然后检查Alpha颜色分量。

在这种情况下,您可以添加一个Rect并查找:

private boolean insideButton(Rectangle buttonRect, Point mousePt) {
    if (buttonRect.contains(mousePt)) {
        int r = buttonRect.height() / 2;
        if (mousePt.x < r) {
            // Left circle with O at (r, r)
            int xFromO = r - mousePt.x;
            int yFromO = r - mousePt.y;
            if (xFromO * xFromO + yFromO * yFromO > r * r) {
                return false; // Outside circle
            }
        }
        if (mousePt.x > buttonRect.right - r) {
            // Right circle:
            ...
        }
        return true;
    }
    return false;
}

答案 1 :(得分:0)

我至少可以想到两种方式。

第一种是制作蒙版图像(黑白),其中(例如)白色表示可点击区域。基本上,您可以根据原始图像的单击拾取点比较蒙版的像素颜色。

另一种方法是构建一个图像映射,基本上使用类似Shape API的东西来允许非矩形形状。这将允许使用Shape#contains来确定鼠标是否在其中单击

在任何一种情况下,您都需要考虑原始图像的x / y位置

答案 2 :(得分:0)

所以,我用Joop的答案解决了我的问题。他的回答并不是我想要的,但它给了我解决问题所需的想法。我找到的解决方案是:

private boolean insideButton(Rectangle buttonRect, Point mousePt) {
    if (buttonRect.contains(mousePt)) {
        int r = (int)buttonRect.getHeight()/2; // radius of either of the circles that make up the sides of the rectangle
        if(mousePt.x <= buttonRect.getWidth()/2) { // if it is on the left of the button
            Point center = new Point((int)buttonRect.getX()+r, (int)buttonRect.getY()+r); // the center of the circle on the left
            double lengthToPoint = Math.pow(Math.pow(mousePt.x-center.x, 2)+Math.pow(mousePt.y-center.y, 2), 1.0/2); // length from center to the point that the user clicked at
            if(lengthToPoint > r && mousePt.x < center.x) { // if it is to the left of the center and out of the circle
                return false;
            } else {
                return true;
            }
        } else { // if it is on the right, the rest of the code is just about the same as the left circle
            Point center = new Point((int)buttonRect.getWidth()-r, (int)buttonRect.getY()+r);
            double lengthToPoint = Math.pow(Math.pow(mousePt.x-center.x, 2)+Math.pow(mousePt.y-center.y, 2), 1.0/2);
            if(lengthToPoint > r && mousePt.x > center.x) {
                return false;
            } else {
                return true;
            }
        }
    } else {
        return false;
    }
}

我知道计算效率有点低,但我想以这种方式呈现它,以便更好地了解我的解决方案的工作原理。