Java GUI构建器 - 如何制作不规则形状的按钮

时间:2014-10-10 19:38:49

标签: java button user-interface builder

我一直在使用NetBeans GUI构建器,我想要做的就是有一张图片(比如一个简笔画)和一个只在我点击棒图本身而不仅仅是整个矩形时才会发生的动作。我用谷歌搜索了几个小时,我找不到任何东西,请帮忙!

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

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>                
}

3 个答案:

答案 0 :(得分:2)

我对此有点好奇所以我测试了创建一个新的组件类型。我采用了这种方法然后当你点击这个组件时它应该用图像像素数据检查鼠标事件位置,如果像素是透明的,则不应该注册鼠标事件。这个实现只处理鼠标按下事件,类很远,但它应该给你一个良好的开端!检查我放在那里的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?
    }
} 

我使用此代码测试了它:

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);
}

并使用此图片:

Sample button image

答案 1 :(得分:1)

没有&#34;不规则形状的按钮&#34; ,不是我知道的......你必须自己做。

这里的问题是你可能会在图像和java组件之间混淆。我的意思是java没有办法确定你的图像中有什么兴趣点,这就是为什么图像被认为是一个矩形。如果你使用flash,photoshop或任何高级绘图工具:那么它有点像差异在矢量和图像之间。

无论如何,要解决您的问题,您可以定义一个与您的棒图具有相同形状的Poligon。为此,您可以定义构成Polygon的Point,如下所示:

//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 
   }
}

现在就这样,如果鼠标点击事件在Polygon pol内部(应该是你的棒图),那么你可以按照你的按钮做的事情

答案 2 :(得分:0)

Swing 本身不能处理非矩形形状的点击事件(据我所知)。您可以尝试捕获click事件上的鼠标位置,并计算此xy坐标是否在您的形状内部。

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

这样你就拥有了一个简单快速的算法...我不会说它是最好的,但也许还不错:)。