簡體   English   中英

Java GUI構建器-如何制作不規則形狀的按鈕

[英]Java GUI builder - How to make an irregular shaped button

我一直在使用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>                
}

我自己對此有點好奇,所以我測試了創建新的組件類型。 我采用的方法是,當您單擊該組件時,它應該使用圖像像素數據檢查鼠標事件的位置,如果像素是透明的,則不應注冊鼠標事件。 此實現僅處理鼠標按下事件,並且類還遠遠沒有完成,但是應該為您提供一個良好的開始! 檢出我放入的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);
}

並使用此圖像:

樣本按鈕圖片

沒有“不規則形狀的按鈕”之類的東西,反正我也不知道……您必須自己動手做。

這里的問題是您可能在圖像和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(應該是簡筆畫)內,則可以執行按鈕打算執行的操作

就我所知,Swing 本身無法處理非矩形形狀的點擊事件。 您可以嘗試在click事件上捕獲鼠標位置,並計算此xy坐標是否在您的形狀內。

我不知道您的圖像是什么樣子,但是它猜測它是透明或至少均勻背景上的某種圖形。 如果是這樣,您可以簡單地檢查xy坐標處的像素顏色是否為特定的背景顏色。

這樣,您就擁有了一個簡單而快速的算法...我不會說這是最好的,但也許足夠好:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM