使用Java实现圆形摇摆JButton

25

我有一张圆形的图片,希望作为按钮(或其他可点击物体)的背景。问题是我需要显示这张图片,没有任何边框等装饰。

包含该按钮的JComponent具有自定义背景,因此该按钮确实只需要显示图片。

在搜索Google后,我无法做到这一点。我尝试了以下所有方法,但都没有成功:

button.setBorderPainted(false);
button.setContentAreaFilled(false);
button.setOpaque(true);

在我将图标绘制到背景后,按钮会将其绘制出来,但是会带有丑陋的灰色背景和边框等。我还尝试使用JLabel和JButton,然后在其上绘制ImageIcon,但是如果用户调整窗口大小或最小化窗口,则会使图标消失!

我该如何解决这个问题?

我只需要将图像绘制并镶嵌到JComponent中,并侦听其点击事件...


您可以检查类似问题的先前答案线程: https://dev59.com/q1TTa4cB1Zd3GeqPuq5Z#31699716 - Tell Me How
9个回答

26
创建一个新的JButton:
    JButton addBtn = new JButton("+");
    addBtn.setBounds(x_pos, y_pos, 30, 25);
    addBtn.setBorder(new RoundedBorder(10)); //10 is the radius
    addBtn.setForeground(Color.BLUE);

在设置JButton的边框时,调用重写的javax.swing.border.Border类。

addBtn.setBorder(new RoundedBorder(10));

这里是类

private static class RoundedBorder implements Border {

    private int radius;


    RoundedBorder(int radius) {
        this.radius = radius;
    }


    public Insets getBorderInsets(Component c) {
        return new Insets(this.radius+1, this.radius+1, this.radius+2, this.radius);
    }


    public boolean isBorderOpaque() {
        return true;
    }


    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
        g.drawRoundRect(x, y, width-1, height-1, radius, radius);
    }
}

8
@UVM这几乎是一个有帮助的评论。能否详细说明为什么它“几乎正确”? - Pete
4
可能是因为矩形背景可见度随着半径的增加而变大。 - omushpapa

14
你试过以下的吗?
button.setOpaque(false);
button.setFocusPainted(false);
button.setBorderPainted(false);
button.setContentAreaFilled(false);
setBorder(BorderFactory.createEmptyBorder(0,0,0,0)); // Especially important

setBorder(null)可能有效,但是Sun的一个bug描述解释了这是设计上的问题,除非客户端设置了一个非空且不实现UIResource接口的边框,否则UI会在组件上设置一个边框。

与其在传入null时JDK自身设置边框为EmptyBorder,客户端应该自己设置EmptyBorder(这是一个非常简单的解决方法)。这样代码中就不会有关于谁在做什么的混淆。


您可以查看类似问题的先前答案线程: https://dev59.com/q1TTa4cB1Zd3GeqPuq5Z#31699716 - Tell Me How

3
我编写了一个OvalButton类,可以处理椭圆形、圆形和胶囊状的JButtons。
在您的情况下,扩展OvalButton类并覆盖getBackgroundImage()方法以返回要设置为背景的图像。然后像通常一样添加侦听器和文本。只有在椭圆形/圆形区域上单击才会触发操作。
您的按钮类示例:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class ImageButton extends OvalButton {

    private BufferedImage image;

    public ImageButton() {
        super(); // Default is oval/circle shape.

        setBorderThickness(0); // Oval buttons have some border by default.

        try {
            image = ImageIO.read(new File("your_image.jpg")); // Replace with the path to your image.
        } 
        catch (IOException e) {
            e.printStackTrace();
            image = null;
        }
    }

    @Override
    protected BufferedImage getBackgroundImage() {
        return image;
    }
}

1
你可以尝试以下方法。对我来说它很有效,我也遇到了与按钮相同的问题。
// Jbutton
JButton imageButton = new JButton();

// Buffered Icon
BufferedImage buttonIcon = null;

try {
    // Get the image and set it to the imageicon
    buttonIcon = ImageIO.read(getClass().getClassLoader().getResource("images/login.png"));
}
catch(Exception ex) {

}

// Set the image icon here
imageButton = new JButton(new ImageIcon(buttonIcon));
imageButton.setBorderPainted(false);
imageButton.setContentAreaFilled(false);
imageButton.setFocusPainted(false);
imageButton.setOpaque(false);

1
  1. 将普通按钮拖到您的面板上

  2. 右键单击按钮,进入属性:

border              = no border
border painted      = false
contentAreaFilled   = false
focusPainted        = false
opaque              = false
  1. 通过导入到项目中设置一个(icon)和一个(rolloverIcon)。

7
"boarder"? 应该是 "border" 吗?"no barder"? 应该是 "no border" 吗?"boarder painted"? 应该是 "border painted" 吗? - Peter Mortensen

1
我建议重写 paint(Graphics g) 方法如下:
class JImageButton extends JComponent implements MouseListener {
    private BufferedImage img = null;

    public JImageButton(BufferedImage img) {
        this.img = img;
        setMinimumSize(new Dimension(img.getWidth(), img.getHeight()));
        setOpaque(false);
        addMouseListener(this);
    }

    public void paintComponent(Graphics g) {
        g.drawImage(img, 0, 0, img.getWidth(), img.getHeight(), null);
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }
}

0

我刚遇到了同样的问题,@Lalchand 的答案给了我灵感。我创建了一个自定义类来实现圆角边框,它实际上是 LineBorder 类的修改版本。它绘制了两个矩形:innerouter。对于我的情况,如果边框的颜色与背景相同就可以了,但如果你需要其他颜色,你应该调整 innerouter 的尺寸。而且,作为创意自由,我使用了亚像素渲染来使边框更加平滑。

import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;

class RoundedBorder extends LineBorder {

    private int radius;
    RoundedBorder(Color c, int thickness, int radius) {
        super(c, thickness, true);
        this.radius = radius;
    }
    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
        // adapted code of LineBorder class
        if ((this.thickness > 0) && (g instanceof Graphics2D)) {
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            Color oldColor = g2d.getColor();
            g2d.setColor(this.lineColor);

            Shape outer;
            Shape inner;

            int offs = this.thickness;
            int size = offs + offs;
            outer = new RoundRectangle2D.Float(x, y, width, height, 0, 0);
            inner = new RoundRectangle2D.Float(x + offs, y + offs, width - size, height - size, radius, radius);
            Path2D path = new Path2D.Float(Path2D.WIND_EVEN_ODD);
            path.append(outer, false);
            path.append(inner, false);
            g2d.fill(path);
            g2d.setColor(oldColor);
        }
    }
}

0

不应该设置不透明度为false,因此

button.setOpaque(false);

可能已经是你想要的了。


-1
您可以像这样为按钮创建一个空边框:
button.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接