2

我用 Java 创建了一个简单的音乐节拍器。它通过按下一个蝴蝶形状的按钮来启动和停止。我很想通过使按钮/蝴蝶随着节拍器节拍出现和消失来添加速度的视觉效果。

java.util.Timer 会是要走的路吗?这是否适用于按钮图像并且需要在脉冲时保持其功能?

非常感谢您对社区的建议和祝贺。

4

1 回答 1

3

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();
         }
      });
   }
}
于 2013-09-10T15:46:17.100 回答