JavaGUI生成器-如何制作不规则形状的按钮

JavaGUI生成器-如何制作不规则形状的按钮,java,button,user-interface,builder,Java,Button,User Interface,Builder,我一直在使用NetBeans GUI builder,我想做的就是有一张图片(比如一个棒状图形)和一个动作,只有在我单击棒状图形本身时才会发生,而不仅仅是单击它的整个矩形。我在谷歌上搜索了几个小时,什么也找不到,请帮忙 编辑:主要问题是我如何让它忽略按钮上的透明像素 package my.usefulness; public class usefulness extends javax.swing.JFrame { public usefulness() { i

我一直在使用NetBeans GUI builder,我想做的就是有一张图片(比如一个棒状图形)和一个动作,只有在我单击棒状图形本身时才会发生,而不仅仅是单击它的整个矩形。我在谷歌上搜索了几个小时,什么也找不到,请帮忙

编辑:主要问题是我如何让它忽略按钮上的透明像素

package my.usefulness;

public class usefulness extends javax.swing.JFrame
{
    public usefulness()
    {
        initComponents();
    }
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jButton1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jButton1.setIcon(new javax.swing.ImageIcon("C:\\Users\\rando_000\\Desktop\\buttonImage.png")); // NOI18N
        jButton1.setBorderPainted(false);
        jButton1.setContentAreaFilled(false);
        jButton1.setFocusPainted(false);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(149, 149, 149)
                .addComponent(jButton1)
                .addContainerGap(200, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jButton1)
                .addGap(0, 237, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                
}
包我的有用性;
公共类扩展javax.swing.JFrame
{
公共效用()
{
初始化组件();
}
@抑制警告(“未选中”)
//                           
私有组件(){
jButton1=newjavax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jButton1.setIcon(新的javax.swing.ImageIcon(“C:\\Users\\rando\u 000\\Desktop\\buttonImage.png”);//NOI18N
jButton1.1(假);
jButton1.setContentAreaFilled(false);
jButton1.setfocuspaint(假);
javax.swing.GroupLayout=newjavax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(布局);
layout.setHorizontalGroup(
createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(149149149)
.addComponent(jButton1)
.addContainerGap(200,简称最大值))
);
layout.setVerticalGroup(
createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jButton1)
.addGap(0,237,短。最大值))
);
包装();
}//                 
}
Swing本身无法处理非矩形形状的单击事件(据我所知)。您可以尝试捕捉单击事件上的鼠标位置,并计算此xy坐标是否在形状内部

我不知道你的图像是什么样子,但我猜它是透明背景上的某种图形。如果是这样,您可以简单地检查该xy坐标处的像素颜色是否为该特定背景色

这样你就有了一个简单快速的算法。。。我不认为这是最好的,但也许已经足够好了:)

没有“不规则形状的按钮”这样的东西,反正我也不知道。。。你得自己做

这里的问题是,您可能会混淆图像和java组件。我的意思是,java无法确定图像中的兴趣点,这就是为什么图像被视为矩形。如果使用flash、photoshop或任何高级绘图工具,那么它有点像矢量和图像之间的区别

无论如何,为了解决您的问题,您可以定义一个与您的棍形形状相同的多边形。为此,请定义构成多边形的点,如下所示:

//a triangle for example 
int[] x = {100,50,150}; // the X postion of the points that form the polygon
int[] y = {100,200,200};// the y pos
Polygon pol = new Polygon(x,y,3) // 3 is number of points .
现在在鼠标事件侦听器中:

 public void mouseClicked(MouseEvent evt){
{
  if(pol.contains(evt.getPoint()){
    // do w.e your button should do 
   }
}

现在这样,如果鼠标单击事件在多边形pol(应该是你的棒状图形)内,那么你可以按按钮的意图操作

我自己对此有点好奇,所以我尝试创建一种新的组件类型。我采取的方法是,当你点击这个组件时,它应该用图像像素数据检查鼠标事件的位置,如果像素是透明的,那么鼠标事件不应该被注册。这个实现只处理鼠标按下事件,类还远未完成,但它应该给您一个好的开始!签出我放在那里的
TODO
标记

public class TransparentImageButton extends JComponent implements MouseListener {

    private BufferedImage image = null;
    private File imageFile;
    private List<ActionListener> listeners;

    public TransparentImageButton(File imageFile) throws IOException {
        this.imageFile = imageFile;
        this.image = ImageIO.read(imageFile);
        this.addMouseListener(this);
        this.listeners = new ArrayList<ActionListener>();
    }

    public void addActionListener(ActionListener listener) {
        listeners.add(listener);
    }

    @Override
    protected void paintComponent(Graphics g) { 
        super.paintComponent(g);
        Rectangle r = getImageBounds();
        g.drawImage(image, r.x, r.y, r.width, r.height, this);
    }


    private Rectangle getImageBounds() {
        // TODO Add in proper handling if component size < image size.
        return new Rectangle((int)((getBounds().width-image.getWidth())/2), (int)((getBounds().height-image.getHeight())/2), image.getWidth(), image.getHeight());
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        // TODO Add more action events?
    }

    @Override
    public void mousePressed(MouseEvent e) {
        Rectangle bounds = getImageBounds();
        if(bounds.contains(e.getPoint())) {
            int ix = e.getX()-bounds.x;
            int iy = e.getY()-bounds.y;
            int [] arr = image.getData().getPixel(ix, iy, new int[4]);
            // get the alpha for the current pixel
            if(arr[3] != 0) {
                // not transparent
                ActionEvent newActionEvent = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, imageFile.getName(), e.getWhen(), e.getModifiers());
                for(ActionListener listener : listeners) {
                    listener.actionPerformed(newActionEvent);
                }
            }
        } else {
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Add more action events?
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Add more action events?
    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Add more action events?
    }
} 
并使用此图像:


好吧,您可以在
onClick()中获取鼠标X,Y。这不是一个好主意,但如果你绝望了……你希望如何区分图上的位置和图上的位置?这将是你问题的决定性因素。我添加了一个编辑,但问题更多的是如何忽略透明像素,对不起,我本来打算对此进行投票,但你打破了油漆链,这可能会导致一些令人讨厌的油漆artifacts@MadProgrammer哎呀,修好了
public static void main(String[] args) throws FileNotFoundException, IOException {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(500, 400);
    frame.setLocationByPlatform(true);

    TransparentImageButton btn = new TransparentImageButton(new File("c:\\icon.png"));
    btn.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Clicky!!");
        }
    });
    frame.getContentPane().add(btn);
    frame.setVisible(true);
}