gpt4 book ai didi

java - JButton悬停效果动画。通过鼠标监听器更改不透明度

转载 作者:行者123 更新时间:2023-12-02 05:30:26 27 4
gpt4 key购买 nike

我想做一个具有良好过渡效果的 JButton。我编写了一个由 JButton 扩展的类并向其添加自定义 MouseAdapter。它几乎可以工作,但如果不透明度应该为 0,我的 BufferedImage 就不会消失。

这是我的所有源代码:

public class ImageHoverButton extends JButton {

public class MouseListener extends MouseAdapter
{
public void mouseExited(MouseEvent me)
{
new Thread(new Runnable()
{
public void run()
{
for (float i = 1f; i >= 0f; i -= .03f)
{
setOpacity(i);
try
{
Thread.sleep(10);
}
catch (Exception e)
{
}
}
}
}).start();
}

public void mouseEntered(MouseEvent me)
{
new Thread(new Runnable()
{
public void run()
{
for (float i = 0f; i <= 1f; i += .03f)
{
setOpacity(i);
try
{
Thread.sleep(10);
}
catch (Exception e)
{
}
}
}
}).start();
}

public void mousePressed(MouseEvent me)
{
new Thread(new Runnable()
{
public void run()
{
for (float i = 1f; i >= 0.6f; i -= .1f)
{
setOpacity(i);
try
{
Thread.sleep(1);
}
catch (Exception e)
{
}
}
}
}).start();
}
}


private static final long serialVersionUID = 1L;

private BufferedImage imgBottom;
private BufferedImage imgHover;
private BufferedImage imgHoverRGB;

// filter to imgInActive
float[] scales = { 1f, 1f, 1f, 0f};
float[] offsets = new float[4];
RescaleOp rop = new RescaleOp(scales, offsets, null);

/**
* Constructor for image path
* @param img
* @param x
* @param y
*/

public ImageHoverButton(String imgBottomPath, String imgHoverPath, int x, int y) {

try {
this.imgBottom = ImageIO.read(new File(imgBottomPath));
this.imgHover = ImageIO.read(new File(imgHoverPath));


imgHoverRGB = new BufferedImage(imgHover.getWidth(null),
imgHover.getHeight(null),
BufferedImage.TYPE_INT_ARGB);
Graphics g = imgHoverRGB.getGraphics();
g.drawImage(imgHover, 0, 0, null);

} catch (IOException e) {
}
this.setBounds(x, y, imgBottom.getWidth() + 40 , imgBottom.getHeight() + 50);
addMouseListener(new MouseListener());
setOpacity(0f);
setOpaque(false);
setBorderPainted(false);
setRolloverEnabled(false);
setCursor(new Cursor(Cursor.HAND_CURSOR));
setLayout(null);



}

public void setOpacity(float opacity) {
scales[3] = opacity;
rop = new RescaleOp(scales, offsets, null);
repaint();
}

public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
g2d.drawImage(imgBottom, 50, 50, null);
g2d.drawImage(imgHoverRGB, rop, 0, 0);
}

}

知道如何改进吗?

最佳答案

我对RescaleOp不太熟悉,并且不记得以前使用过它。但在这个案例中应用它的结果似乎有些出乎意料。

作为替代方案,您可以考虑使用 AlphaComposite。达到预期效果所需的最小修改就是更改行

g2d.drawImage(imgHoverRGB, rop, 0, 0);

g2d.setComposite(AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, scales[3]));
g2d.drawImage(imgHoverRGB, 0, 0, null);

但是,代码还存在其他几个问题:

  • 不要覆盖paint。相反,重写paintComponent
  • 不要在组件上调用setBounds(尤其是在构造函数中)。放置应由布局管理器完成
  • 不要默默地接受异常
  • 不要在按钮的构造函数中加载图像
  • 正确实现getPreferredSize
  • 不要由于鼠标移动而产生数百个线程。 (当您快速移入和移出鼠标时,您将运行多个线程 - 其中一些线程会增加不透明度,而另一些则会降低不透明度)

我创建了一个示例,展示了一种可能的方法:它包含一个 OpacityAnimator,允许在两个不透明度之间进行转换,并具有以毫秒为单位的预定义延迟。该动画器用于在鼠标悬停在按钮上时增加前景图像的不透明度,并在鼠标离开按钮时减少前景图像的不透明度。

(请注意,这可以进一步推广,并且可以公开许多可能的“配置设置”(例如转换延迟),但这只是作为示例)

import java.awt.AlphaComposite;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class HoverButtonTest
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
try
{
createAndShowGUI();
}
catch (IOException e)
{
e.printStackTrace();
}
}
});
}

private static void createAndShowGUI() throws IOException
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

BufferedImage backgroundImage = loadImage("background.png");
BufferedImage foregroundImage = loadImage("foreground.png");
f.getContentPane().setLayout(new FlowLayout());
f.getContentPane().add(
new ImageHoverButton(backgroundImage, foregroundImage));

f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}

private static BufferedImage loadImage(String path) throws IOException
{
return convertToARGB(ImageIO.read(new File(path)));
}

public static BufferedImage convertToARGB(BufferedImage image)
{
BufferedImage newImage = new BufferedImage(image.getWidth(),
image.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}

}

class ImageHoverButton extends JButton
{
private class MouseHoverListener extends MouseAdapter
{
@Override
public void mouseExited(MouseEvent me)
{
opacityAnimator.changeOpacity(0.0f, 250);
}

@Override
public void mouseEntered(MouseEvent me)
{
opacityAnimator.changeOpacity(1.0f, 1000);
}

@Override
public void mousePressed(MouseEvent me)
{
opacityAnimator.changeOpacity(0.5f, 50);
}
}

private class OpacityAnimator
{
private final int DELAY_MS = 10;
private final Timer timer;

private float targetOpacity;
private float currentOpacity;
private float opacityStep;

OpacityAnimator()
{
timer = new Timer(DELAY_MS, new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
if (currentOpacity > targetOpacity)
{
currentOpacity += opacityStep;
currentOpacity = Math.max(
currentOpacity, targetOpacity);
}
else if (currentOpacity < targetOpacity)
{
currentOpacity += opacityStep;
currentOpacity = Math.min(
currentOpacity, targetOpacity);
}
if (currentOpacity == targetOpacity)
{
timer.stop();
}
setOpacity(currentOpacity);
}
});
}

void changeOpacity(float targetOpacity, int durationMs)
{
timer.stop();
this.targetOpacity = targetOpacity;

float delta = targetOpacity - currentOpacity;
if (durationMs > 0)
{
opacityStep = (delta / durationMs) * DELAY_MS;
}
else
{
opacityStep = delta;
}
timer.start();
}
}

private final OpacityAnimator opacityAnimator;
private final BufferedImage backgroundImage;
private final BufferedImage foregroundImage;
private float opacity = 0.0f;

public ImageHoverButton(BufferedImage backgroundImage,
BufferedImage foregroundImage)
{
this.backgroundImage = backgroundImage;
this.foregroundImage = foregroundImage;
this.opacityAnimator = new OpacityAnimator();
addMouseListener(new MouseHoverListener());
setOpaque(false);
setBorderPainted(false);
setRolloverEnabled(false);
setCursor(new Cursor(Cursor.HAND_CURSOR));
}

@Override
public Dimension getPreferredSize()
{
if (super.isPreferredSizeSet())
{
return super.getPreferredSize();
}
int w = Math
.max(backgroundImage.getWidth(), foregroundImage.getWidth());
int h = Math.max(backgroundImage.getHeight(),
foregroundImage.getHeight());
return new Dimension(w, h);
}

public void setOpacity(float opacity)
{
this.opacity = opacity;
repaint();
}

@Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D) gr;
g.drawImage(backgroundImage, 0, 0, null);
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
opacity));
g.drawImage(foregroundImage, 0, 0, null);
}
}

关于java - JButton悬停效果动画。通过鼠标监听器更改不透明度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25601567/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com