2

我发现了 2 种不适合我的不同解决方案。第一个涉及透明度。第二个我更喜欢,因为它看起来更干净。目标是使用具有透明度的图像创建自定义形状的按钮。我想忽略透明部分,仅在单击图像的非透明部分时才采取行动。

第一个代码来自这里http://java.macteki.com/2012/07/custom-shape-buttons.html。顺便问一下,下面代码中的 0x00ffffff 有什么意义?

//********** BEGIN OF IMAGE BUTTON CODE ****************
      // The following is the actual code to create a image button
      // you may use any transparent image file, just change "a.png" below
      final BufferedImage image = ImageIO.read(new File("a.png"));
      ImageIcon icon = new ImageIcon(image);

      jLabel1 = new javax.swing.JLabel(icon);
      jLabel1.addMouseListener(new MouseAdapter()
      {
      public void mouseClicked(MouseEvent e)
      {
      boolean transparent = (image.getRGB(e.getX(),e.getY()) & 0x00ffffff)!=0;
     if (!transparent) {
      // write your button handler here
       System.out.println("button pressed");
      } else {
        System.out.println("else");
      }
      }
      }

      );
      //********** END OF IMAGE BUTTON CODE ****************
      // add the button to the panel so that it becomes visible

它适用于他的测试图像,但不适用于我的任何图像。我什至拿走了他,只是改变了 gimp 中 A 的颜色,导出到 a2.png 并且它不起作用。它将所有区域注册为else并且if (!transparent)从不触发。

此图像有效: 此图像有效 此图像无效: 此图无效

我更喜欢的第二个代码来自这里用 JButton 在 Java 中创建自定义按钮。图像适用于按钮,但在框中的任意位置(包括透明区域)单击将注册为单击。我希望它仅在您单击非透明区域(或本例中的 A)时才起作用。

BufferedImage startButton = ImageIO.read(new File("a2.png"));       
        jButton1 = new javax.swing.JButton(new ImageIcon(startButton));  
        jButton1.setBorder(BorderFactory.createEmptyBorder());
        jButton1.setContentAreaFilled(false);
        jButton1.setFocusable(false);

这是我根据 Guillame 的示例尝试使用的代码

private void initComponents() throws IOException {

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        final BufferedImage image = ImageIO.read(getClass().getResource("/images/a.png"));
        jButton1 = new JButton(new ImageIcon(image)) {
             @Override
             public boolean contains(int x, int y) {
                 Rectangle viewRect = getBounds();
                 Insets insets = getInsets();
                 viewRect.x += insets.left;
                 viewRect.y += insets.top;
                 viewRect.width -= insets.left + insets.right;
                 viewRect.height -= insets.top + insets.bottom;
                 Rectangle iconR = new Rectangle();
                 SwingUtilities.layoutCompoundLabel(this, this.getFontMetrics(this.getFont()), this.getText(), this.getIcon(),
                         this.getVerticalAlignment(), this.getHorizontalAlignment(), this.getVerticalTextPosition(),
                         this.getHorizontalTextPosition(), viewRect, iconR, new Rectangle(), this.getIconTextGap());
                 if (!iconR.contains(x, y)) {
                     return false;
                 }
                 x -= iconR.x;
                 y -= iconR.y;
                 Color c = new Color(image.getRGB(x, y), true);
                 return c.getAlpha() != 0 && (c.getRed() < 255 || c.getGreen() < 255 || c.getBlue() < 255);
             }
         };

        jButton1.setContentAreaFilled(false); 
        jButton1.setFocusPainted(false);            
        jButton1.setRolloverEnabled(false);       
        jButton1.setBorderPainted(false);

        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        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(72, 72, 72)
                .addComponent(jButton1)
                .addContainerGap(255, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(193, Short.MAX_VALUE)
                .addComponent(jButton1)
                .addGap(84, 84, 84))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents
4

1 回答 1

4

您需要覆盖 的方法才能contains(int,int)使JButton您的第二种方法起作用。现在最难的部分是弄清楚你是否在图像的相关部分。在这种情况下,我假设完全透明的像素不相关,白色像素也不相关。由您选择不同的实现:

import java.awt.Color;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

public class TestTransparentButton {

    protected void createAndShowGUI() throws MalformedURLException, IOException {
        JFrame frame = new JFrame("Test button");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final BufferedImage image = ImageIO.read(new URL("http://i.stack.imgur.com/7D547.png"));
        final JButton button = new JButton(new ImageIcon(image)) {
            @Override
            public boolean contains(int x, int y) {
                Rectangle viewRect = getBounds();
                Insets insets = getInsets();
                viewRect.x = insets.left;
                viewRect.y = insets.top;
                viewRect.width -= insets.left + insets.right;
                viewRect.height -= insets.top + insets.bottom;
                Rectangle iconR = new Rectangle();
                SwingUtilities.layoutCompoundLabel(this, this.getFontMetrics(this.getFont()), this.getText(), this.getIcon(),
                        this.getVerticalAlignment(), this.getHorizontalAlignment(), this.getVerticalTextPosition(),
                        this.getHorizontalTextPosition(), viewRect, iconR, new Rectangle(), this.getIconTextGap());
                if (!iconR.contains(x, y)) {
                    return false;
                }
                x -= iconR.x;
                y -= iconR.y;
                Color c = new Color(image.getRGB(x, y), true);
                return c.getAlpha() != 0 && (c.getRed() < 255 || c.getGreen() < 255 || c.getBlue() < 255);
            }
        };
        button.setContentAreaFilled(false);
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(button, "You clicked on the button");
            }
        });
        frame.add(button);
        frame.setSize(200, 200);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    new TestTransparentButton().createAndShowGUI();
                } catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });

    }

}
于 2013-01-16T16:50:26.413 回答