简体   繁体   English

如何创建复杂的Button形状?

[英]How can i create a complex Button shape?

I have a frame with an image covering it, And i want that every time some one clicks on a different object in the image , it will act as a button and do something. 我有一个框架,图像覆盖它,我希望每次有人点击图像中的不同对象,它将作为一个按钮,做一些事情。
The problem is , Is that those objects are not simple shapes, so i was thinking about drawing my own invisible buttons in the shape of those objects. 问题是,这些对象是不是简单的形状,所以我想在这些对象的形状中绘制我自己的隐形按钮。

Is that possible? 那可能吗? or what would be a better way to accomplish such a thing? 或者什么是更好的方式来完成这样的事情?

-thank you -谢谢

Define an interface for a region like: 为以下区域定义接口:

//represents any clickable area.
public interface IButton{
    boolean contains(int x, int y);
}

Then, if you want a circular area to be clickable, define a class which checks if ax,y coordinate is within some distance of a position. 然后,如果要使圆形区域可单击,请定义一个类,用于检查ax,y坐标是否在某个位置的某个距离内。

public class CircleButton implements IButton{
    Point center;
    double radius;   
    public CircleButton(int x, int y, double radius){
        this.center = new Point(x,y);
        this.radius = radius;
    }
    //check if x,y coords are within a radius 
    //from the center of this circle button
    public boolean contains(int x, int y){
        double dx = x-center.x;
        double dy = y-center.y;
        return (Math.sqrt(dx*dx+dy*dy) <= radius);
    }
}

Create a list of IButtons. 创建IButtons列表。 You'll iterate over these to see if a user clicked on one of your invisible buttons. 您将迭代这些以查看用户是否单击了您的一个隐形按钮。

List<IButton> buttons = new List<IButton>();
buttons.add(new CircleButton(100,100,200);

Then each time someone clicks on your frame iterate over your invisible buttons using the location of that mouse click. 然后,每当有人点击你的框架时,使用鼠标点击的位置迭代你的隐形按钮。

public void mouseReleased(MouseEvent e){
    for(IButton b : buttons){
       if(b.contains(evt.getX(),e.getY()){
           //do something depending on what button was clicked.
       }
    }
} 

You can easily see how you could define invisible rectangle buttons like this, or even irregular polygon shapes. 您可以轻松地看到如何定义这样的隐形矩形按钮,甚至是不规则的多边形形状。 You'd just need to implement the contains method correctly. 您只需要正确实现contains方法。

Concept: invisible buttons with circular and polygonal dispatch areas 概念:具有圆形和多边形调度区域的隐形按钮

First, you'll want a class defining an invisible button, extending javax.swing.AbstractButton so that it's still a fully functional button that you can add listeners to. 首先,你需要一个定义一个不可见按钮的类,扩展javax.swing.AbstractButton这样它仍然是一个可以添加监听器的全功能按钮。

public abstract class InvisibleButton extends AbstractButton {

    public abstract boolean contains(Point point);

    @Override
    public boolean isVisible() {
        return false;
    }
}

Then, of course, you'll want implementations of that class. 然后,当然,您将需要该类的实现。 Here's two examples: one using a polygon for complex shapes, one using a circle. 这里有两个例子:一个使用多边形复杂形状,一个使用圆形。

public class PolygonalButton extends InvisibleButton {

    private Polygon area = null;

    public PolygonalButton(Polygon area) {
        this.area = area;
    }

    @Override
    public boolean contains(Point point) {
        return area.contains(point);
    }
}

public class CircularButton extends InvisibleButton {

    private int x;
    private int y;
    private double radius;

    public CircularButton(int x, int y, double radius) {
        this.x = x;
        this.y = y;
        this.radius = radius;
    }

    @Override
    public boolean contains(Point point) {
        double dx = x - point.x;
        double dy = y - point.y;
        return Math.sqrt(dx * dx + dy * dy) <= radius;
    }
}

Finally, you'll need to implement a container that handles all of these buttons, but you should use a panel instead of a frame. 最后,您需要实现一个处理所有这些按钮的容器,但您应该使用面板而不是框架。 Rather than hook each individual listener, you can simply override the frame's event processors and pass them to the necessary buttons. 您可以简单地覆盖框架的事件处理器并将它们传递给必要的按钮,而不是挂钩每个单独的侦听器。

public class InvisibleButtonImagePanel extends JPanel {

    private BufferedImage image = null;
    private List<InvisibleButton> buttons = new ArrayList<>();

    public InvisibleButtonImagePanel(BufferedImage image) {
        this.image = image;
    }

    public void add(InvisibleButton button) {
        buttons.add(button);
    }

    public void remove(InvisibleButton button) {
        buttons.remove(button);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(image.getWidth(), image.getHeight());
    }

    @Override
    public void processKeyEvent(KeyEvent event) {
        for (InvisibleButton button : buttons) {
            if (button.isFocusOwner()) {
                button.dispatchEvent(event);
            }
        }
        super.processKeyEvent(event);
    }

    @Override
    public void processMouseEvent(MouseEvent event) {
        for (InvisibleButton button : buttons) {
            if (button.contains(event.getPoint())) {
                button.dispatchEvent(event);
            }
        }
        super.processMouseEvent(event);
    }

    @Override
    protected void paintComponent(Graphics g) {
        g.drawImage(image, 0, 0, null);
        super.paintComponent(g);
    }
}

You'll probably want to rename the panel to something less bulky, and maybe implement your own advanced image code, but that's the basic idea behind it. 您可能希望将面板重命名为不那么笨重的东西,并且可能实现您自己的高级图像代码,但这是它背后的基本思想。

Can you track the users mouse position via Coordinates? 您可以通过坐标跟踪用户鼠标位置吗?

 PointerInfo a = MouseInfo.getPointerInfo();
        Point b  = a.getLocation();
        int x = (int)b.getX();
        int y = (int)b.getY();

Now put a ActionPerformed Method and test if x and y = eg 200, 300 do this . 现在放一个ActionPerformed方法并测试x和y =例如200,300 这样做 That way when a user clicks on a spot (your aiming for area) it will redirect him to a method. 这样,当用户点击某个地点(您的目标是区域)时,它会将他重定向到某个方法。

And i want that every time some one clicks on a different object in the image , it will act as a button and do something. 我希望每当有人点击图像中的不同对象时,它就会充当按钮并执行某些操作。

You can create an ArrayList of Shape objects. 您可以创建Shape对象的ArrayList。 Then you add a MouseListener to the component containing the image. 然后将MouseListener添加到包含图像的组件中。 Whenever a mousePressed event is generated you loop through the ArrayList and use the containts(...) method of the component to determine if the user click on a Shapes corrdinates. 每当生成mousePressed事件时,您都会遍历ArrayList并使用组件的containts(...)方法来确定用户是否单击Shapes corrdinates。

Check out Playing With Shapes . 看看玩形状 The code won't help with your immediate problem, but it will give you an idea of the type of Shapes that you can define. 代码对您的直接问题没有帮助,但它会让您了解可以定义的Shapes类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM