【问题标题】:How to play multiple WAV files when different buttons are clicked?单击不同的按钮时如何播放多个WAV文件?
【发布时间】:2020-06-12 03:26:06
【问题描述】:

我正在用 Java 创建一个简单的音频拨号器。我已经完成了按钮及其功能的设置,就像在文本字段中显示它一样。我只是不知道如何让我的按钮在单击时发出音调。我还需要他们在按下“拨号”后播放所有号码的音调(比如当你打电话给某人时)。我有大约 12 个用于音调的 WAV 文件,这是我迄今为止的帧代码(不是驱动程序类)。

public class dialerFrame extends JFrame
{
    private JTextField display;// creating text field display
    private static final int FRAME_WIDTH = 500;// frame width
    private static final int FRAME_HEIGHT = 500;// frame height
    private JButton numButton, clrButton, backButton, dialButton;//creating all buttons needed

    /**
     * Constructor to build frame
     */
    public dialerFrame()
    {
        display = new JTextField ("");//setting text field to empty 
        display.setEditable(false);//setting text field to not take in values
        add(display, BorderLayout.NORTH);//assigning north region for the text field and adding to frame
        createNumButtonPanel();
        createOperatorButtonPanel();
        setSize(FRAME_WIDTH, FRAME_HEIGHT);//
    }

    /**
     * Method to construct all numeric buttons from 1-9 and set layout
     */
    private void createNumButtonPanel()
    {
        JPanel numButtonPanel = new JPanel();// creating a panel for numbers and symbols only
        numButtonPanel.setLayout(new GridLayout(4,3));//setting 4 by 3 grid layout for the panel

        //adding the buttons on the panel
        numButtonPanel.add(makeDigitButton("1"));
        numButtonPanel.add(makeDigitButton("2"));
        numButtonPanel.add(makeDigitButton("3"));
        numButtonPanel.add(makeDigitButton("4"));
        numButtonPanel.add(makeDigitButton("5"));
        numButtonPanel.add(makeDigitButton("6"));
        numButtonPanel.add(makeDigitButton("7"));
        numButtonPanel.add(makeDigitButton("8"));
        numButtonPanel.add(makeDigitButton("9"));
        numButtonPanel.add(makeDigitButton("*"));
        numButtonPanel.add(makeDigitButton("0"));
        numButtonPanel.add(makeDigitButton("#"));

        add(numButtonPanel, BorderLayout.CENTER);//adding panel to frame in the center
    }

    /**
     * Method to construct operator buttons and assign their function separately 
     */
    private void createOperatorButtonPanel()
    {
        JPanel operatorButtonPanel = new JPanel(new GridLayout(1,3));//creating panel for the operator buttons
        OperatorButtonListener listener = new OperatorButtonListener();// listener for operator buttons
        //creating operator buttons and assigning action listener 
        clrButton = new JButton("CLR");
        clrButton.addActionListener(listener);
        backButton = new JButton("BACK");
        backButton.addActionListener(listener);
        dialButton = new JButton("DIAL");
        dialButton.addActionListener(listener);

        //adding operator buttons to panel
        operatorButtonPanel.add(clrButton);
        operatorButtonPanel.add(backButton);
        operatorButtonPanel.add(dialButton);

        //adding panel to frame in the south region
        add(operatorButtonPanel, BorderLayout.SOUTH);
    }

    /**
     * Inner class listener for the numeric buttons
     */
    private class DigitButtonListener implements ActionListener
    {
        private String digit;

         public DigitButtonListener(String digit)
         {
             this.digit = digit;
         }

         /**
          * Overriding actionPerformed method to be used by the numeric buttons
          */
         public void actionPerformed(ActionEvent event) 
         {
             display.setText(display.getText() + digit);//displaying the corresponding digit on the text field
         }
    }

    /**
     *Inner class listener for operator buttons
     */
    private class OperatorButtonListener implements ActionListener
    {
        /**
        * Overriding actionPerformed method to be used for by the operator Button
        */
        public void actionPerformed (ActionEvent event)
        {
            if(event.getSource() == backButton)
            {
                display.setText(""+display.getText().substring(0, display.getText ().length() - 1));// remove last character
            }
            if(event.getSource() == clrButton)
            {
                display.setText("");// clear text field
            }
            if(event.getSource() == dialButton)
            {

            }
        }
    }

    /**
     * Makes a button representing a digit of the dialer.
     * @param digit takes in digit for dialer 
     * @return numButton the respective button of the dialer
     */
    public JButton makeDigitButton(String digit)
    {
        numButton = new JButton(digit);
        ActionListener listener = new DigitButtonListener(digit);
        numButton.addActionListener (listener);
        return numButton;
    }
}

【问题讨论】:

  • 1) 类名应以大写字符开头。 2)你为什么发布所有这些代码?你的问题是关于播放声音。要了解播放声音的概念,您可以从一个简单的示例开始,而不是整个应用程序。因此,您只需要一个带有单个按钮的框架。请参阅:stackoverflow.com/a/44500689/131872 以获得一个简单的示例。 我还需要他们播放所有的数字 - 所以你需要知道一个声音何时结束,你才能播放另一个。我相信您可以在Clip 中添加一个LineListener,当声音停止时会生成一个事件。
  • 1) 为了尽快获得更好的帮助,edit 添加minimal reproducible exampleShort, Self Contained, Correct Example。为了使代码更短,从实现 two 键的功能开始。一旦它起作用,应该清楚如何添加剩余的键。 2) 请对代码和代码 sn-ps、HTML/XML 等结构化文档或输入/输出使用代码格式。为此,请选择文本并单击消息发布/编辑表单顶部的{} 按钮。 3) 使用逻辑一致的形式缩进代码行和块。缩进..
  • .. 旨在使代码流更易于遵循!大多数 IDE 都有专门用于格式化代码的键盘快捷键。 4) 源代码中的一个空白行是永远需要的。 { 之后或} 之前的空行通常也是多余的。 5) 请学习常见的 Java 命名法(命名约定 - 例如EachWordUpperCaseClassfirstWordLowerCaseMethod()firstWordLowerCaseAttribute,除非它是 UPPER_CASE_CONSTANT)并始终如一地使用它。例如。 (我注意到的那个)dialerFrame 应该是DialerFrame。 ..
  • .. 6) 但话虽如此,不要扩展JFrame,只需使用一个实例,就像代码使用JButtonJTextField 的普通实例一样。 7) 对于手头的任务,使用Java Sound 中的Clip 播放WAVS。或者,稍微复杂一点,在运行时在内存中生成音调。
  • 好的,但是我将如何导入我的 wav 文件以通过任何按钮播放?还有一种方法可以获取按钮的标签吗?我不是在谈论名称,因为我为 12 个按钮分配了 1 个名称,因为它们做同样的事情,但我需要它们播放不同的声音,所以有没有一种方法可以让我在按钮上打印标签而不是名称。

标签: java swing jbutton javasound


【解决方案1】:

这有点棘手,IDK 您在多线程方面的经验如何。

首先,我会尝试使用 MVC 模式。您已经设置了 View 部分的基础知识。对于Model,也许enum 类对电话号码的每个号码都有意义,其中每个enum 与一个ID 相关联,一个String 用于显示和一个相关联的Clip (预加载)或.wav 文件地址(如果使用SourceDataLine),以及可能一种播放方法。

然后,Control 的一个关键功能是连续播放电话号码,可能在其自己的线程中,这样您就不会死在水中等待声音完成播放。

我会让这个控制器成为一个类,并让它实现一个LineListener 并让它响应Line.EventType.STOP(可能只是为松散耦合的方法设置一个状态标志/布尔值)作为管理排序的一种方式和个人ClipSourceDataLine 播放的时间。 (@camickr 在评论中提到了这一点)

我还将启动在其自己的线程中执行电话号码播放的部分。它可以是控制器类中的私有类,因此可以参考父类的 LineListener 实现来检查何时继续“下一个”声音。

这是基本的平面图。还有一些细节需要解决,但希望这会帮助你继续前进。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多