我用 Java 创建了一个简单的音乐节拍器。它通过按下一个蝴蝶形状的按钮来启动和停止。我很想通过使按钮/蝴蝶随着节拍器节拍出现和消失来添加速度的视觉效果。
java.util.Timer 会是要走的路吗?这是否适用于按钮图像并且需要在脉冲时保持其功能?
非常感谢您对社区的建议和祝贺。
java.util.Timer 会是要走的路吗?
是的,这可以很容易地用于显示脉动图像。当我之前完成此操作时,我在构造函数中创建了一个正弦波常量数组,并使用它们在计时器内设置了一个 alpha 组合。
这是否适用于按钮图像并且需要在脉冲时保持其功能?
这可能虽然有点困难,因为按钮并没有真正呈现它自己,而是它的 componentUI,这里是 BasicButtonUI 的子类之一。
好吧,我可以在不弄乱componentUI的情况下做到这一点,但我不确定这是否是正确的方法:
import java.awt.AlphaComposite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@SuppressWarnings("serial")
public class PulsingButton extends JPanel {
private static final int MAX_ALPHAS = 60;
private float alpha = 1.0f;
private JSpinner beatsPerMinSpinner = new JSpinner(new SpinnerNumberModel(60, 30, 120, 1));
private JButton button = new JButton("Button") {
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setComposite(((AlphaComposite)g2.getComposite()).derive(alpha));
super.paintComponent(g2);
};
};
private float[] alphas = new float[MAX_ALPHAS];
private Timer timer;
public PulsingButton() {
beatsPerMinSpinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
int value = ((Integer) beatsPerMinSpinner.getValue()).intValue();
setTimerDelay(value);
}
});
add(new JLabel("Beats Per Minute:"));
add(beatsPerMinSpinner);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Hello!");
}
});
add(button);
for (int i = 0; i < alphas.length; i++) {
double theta = (Math.PI * 2 * i) / alphas.length;
alphas[i] = (float) ((Math.cos(theta) + 1) / 2.0);
}
int bpm = ((Integer) beatsPerMinSpinner.getValue()).intValue();
timer = new Timer(setTimerDelay(bpm), new TimerListener());
timer.start();
System.out.println(setTimerDelay(bpm) + "");
}
private int setTimerDelay(int bpm) {
int milisecondsInMinute = 60 * 1000;
int delay = milisecondsInMinute / (bpm * alphas.length);
if (timer != null) {
timer.setDelay(delay);
}
return delay;
}
private class TimerListener implements ActionListener {
int index = 0;
@Override
public void actionPerformed(ActionEvent arg0) {
alpha = alphas[index];
index++;
index %= alphas.length;
repaint();
}
}
private static void createAndShowGui() {
PulsingButton mainPanel = new PulsingButton();
JFrame frame = new JFrame("PulsingButton");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}