java从包含透明像素的图像创建自定义JButton
阅读编辑2,了解我真正缺少的东西,以使其发挥作用
我目前正在尝试使用photoshop中创建的带有alpha参数的图像创建一些自定义JButton
到目前为止,覆盖paint()方法来绘制图像已经起到了作用,因为绘制的按钮显示了正确的图像。不过,我想改进它,使其形状(可点击区域)与图像上的可见像素相同(现在如果我画按钮的边框,它是一个正方形)
有没有一种简单的方法可以做到这一点,或者我必须解析图像并找到alpha像素来创建自定义边框
我必须重写哪些方法才能使其按我想要的方式工作
还有一个问题,我稍后会问:是否最好使用某种算法来更改图像的颜色,使其看起来像是在人们单击时被单击,还是在按钮处于活动状态时创建第二个图像并绘制该图像更好
编辑:我刚读到另一个问题,我应该重新定义paintComponent()而不是paint(),我想知道为什么重新定义paint()效果很好
编辑2:我更改了所有内容,以确保使用带有图标的默认构造函数创建jbutton。我要做的是获取点击注册位置的X和Y位置,并在该位置抓取图标的像素,检查其alpha通道是否为0(如果为0,则不执行任何操作,否则执行它应该执行的操作)
问题是,alpha通道总是返回255(在透明像素上,蓝色、红色和绿色为238)。在其他像素上,一切都返回它应该返回的值
下面是一个重新创建我的问题的示例(如果需要,请尝试使用另一个图像):
public class TestAlphaPixels extends JFrame
{
private final File FILECLOSEBUTTON = new File("img\\boutonrondX.png"); //My round button with transparent corners
private JButton closeButton = new JButton(); //Creating it empty to be able to place it and resize the image after the button size is known
public TestAlphaPixels() throws IOException
{
setLayout(null);
setSize(150, 150);
closeButton.setSize(100, 100);
closeButton.setContentAreaFilled(false);
closeButton.setBorderPainted(false);
add(closeButton);
closeButton.addMouseListener(new MouseListener()
{
public void mouseClicked(MouseEvent e)
{
}
public void mousePressed(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
System.out.println("Alpha value of pixel (" + e.getX() + ", " + e.getY() + ") is: " + clickAlphaValue(closeButton.getIcon(), e.getX(), e.getY()));
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
});
Image imgCloseButton = ImageIO.read(FILECLOSEBUTTON);
//Resize the image to fit the button
Image newImg = imgCloseButton.getScaledInstance((int)closeButton.getSize().getWidth(), (int)closeButton.getSize().getHeight(), java.awt.Image.SCALE_SMOOTH);
closeButton.setIcon(new ImageIcon(newImg));
}
private int clickAlphaValue(Icon icon, int posX, int posY)
{
int width = icon.getIconWidth();
int height = icon.getIconHeight();
BufferedImage tempImage = (BufferedImage)createImage(width, height);
Graphics2D g = tempImage.createGraphics();
icon.paintIcon(null, g, 0, 0);
g.dispose();
int alpha = (tempImage.getRGB(posX, posY) >> 24) & 0x000000FF;
return alpha;
}
public static void main(String[] args)
{
try
{
TestAlphaPixels testAlphaPixels = new TestAlphaPixels();
testAlphaPixels.setVisible(true);
testAlphaPixels.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
}
}
这只是一个猜测,但有没有可能当我的图像被投射到图标时,它会丢失其Alpha属性,因此不会返回正确的值?无论如何,如果有人真的能帮助我,告诉我应该改变什么以获得正确的值,我会非常感激
我猜这是因为当我尝试原始图像时,alpha通道的值很好,但我不能实际使用BuffereImage,因为我调整了它的大小,所以我实际上得到了原始大小的图像的通道值
# 1 楼答案
如果您想拥有特定于形状的点击点,最好使用shape及其
contains
方法。如果需要,可以在创建自定义按钮类时创建一个形状,并通过环绕形状的contains
方法实现contains方法对于自定义JButton,创建一个扩展JButton的类,如下所示:
如果您想这样做,可以通过以下方式加载ImageIcon
这会给你一个按钮,至少看起来像你的形象。 我问了一个类似的问题,关于基于图像的点击事件,形状有助于创造奇迹。 我想这取决于你的按钮图像有多复杂。 以下是参考资料:
How can you detect a mouse-click event on an Image object in Java?
PS:也许可以考虑从图像中生成形状,这些形状围绕着所有不透明的像素。不知道这是否可行,但这意味着只有用户点击按钮的图像部分,按钮才会被“按下”。只是一个想法
# 2 楼答案
如果你希望你的按钮布局是图像中的不透明像素,那么你应该重新定义
paintComponent()
方法。这是最正确的方法(覆盖paint()在旧时代起作用,但现在不被鼓励)然而,我认为这并不是你想要的:你只想在非透明像素上点击按钮时被检测到,对吗?在这种情况下,您必须解析图像,并在单击时将鼠标坐标与图像的像素alpha通道进行比较,因为JButton没有这样的功能
# 3 楼答案
我认为你走错了路。不必重写paint()或paintComponent()方法。JButton已经“知道”只显示图像:
例如,请参阅以下教程:http://www.apl.jhu.edu/~hall/java/Swing-Tutorial/Swing-Tutorial-JButton.html
此外,swing是完全定制的。您可以控制不透明度、边框、颜色等。您可能应该覆盖上面提到的一些方法来更改功能。但在大多数情况下,有更好、更简单的解决方案
# 4 楼答案
如果你有一个圆形按钮,这正是你需要的:
JButton有一个
contains()
方法。覆盖它并在mouseReleased()上调用它# 5 楼答案
paintComponent()
而不是paint()
取决于paint()
是在XxxButtonUI内还是只覆盖^{# 6 楼答案
因为多个答案中都有好的元素,但没有一个答案是完整的,所以我会回答自己的问题,这样其他有相同问题的人可以尝试类似的方法
我使用一个扩展了JButton的新类创建了我的按钮,并使用了一个新的构造函数,该构造函数将BuffereImage作为参数,而不是图标。原因是当我做了一些像我的按钮。getIcon(),它将返回一个图标,然后我必须对其进行各种操作,使其成为大小合适的BuffereImage,结果它无论如何都无法工作,因为它似乎是第一次对图标进行强制转换,使其丢失了像素中的alpha数据,所以我无法检查用户是否单击了透明像素
所以我为构造器做了这样的事情:
然后,我为我的bufImg创建了一个访问器,它使用getSize()方法调整了图像的大小以适应JButton,然后返回了一个大小正确的图像。我在getBufImg()访问器中进行转换,因为当窗口调整大小时,图像大小可能会改变。调用getBufImg()时,通常是因为单击了按钮,因此当前没有调整窗口的大小
类似这样的操作将以正确的大小返回图像:
使用该缓冲图像,您可以编写如下方法:
你可以点击按钮来实现鼠标听器,如下所示:
瞧!只有在单击不透明像素时,该按钮才会执行该操作
谢谢大家的帮助,我不可能独自想出这个解决方案