-1

I am creating a simple tone dialer in Java. I am done putting up the buttons and their functionalities as in displaying it in the text field and all that. I just don't know how to get my buttons to make tones when clicked. I also need them to play all the numbers' tones once "Dial" is pressed (like when you call someone). I have about 12 WAV files for the tones and this is my code for the frame so far (not Driver class).

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;
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 1) Class names should start with an upper case character. 2) Why did you post all this code? Your question is about playing a sound. To learn the concept of playing a sound you start with a simple example, not an entire application. So all you need is a frame with a single button. See: https://stackoverflow.com/a/44500689/131872 for a simple example. *I also need them to play all the numbers* - so then you need to know when one sound has finished to you can play another. I believe you can add a `LineListener` to the `Clip` an event will be generated when the sound stops. – camickr Jun 12 '20 at 03:48
  • 1) For better help sooner, [edit] to add a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). To make the code shorter, start with implementing the functionality for **two** keys. Once that is working, it should be clear how to add the remaining keys. 2) Please use code formatting for code and code snippets, structured documents like HTML/XML or input/output. To do that, select the text and click the `{}` button at the top of the message posting/editing form. 3) Use a logical and consistent form of indenting code lines and blocks. The indentation .. – Andrew Thompson Jun 12 '20 at 03:49
  • .. is intended to make the flow of the code easier to follow! Most IDEs have a keyboard shortcut specifically for formatting code. 4) A single blank line of white space in source code is all that is *ever* needed. Blank lines after `{` or before `}` are also typically redundant. 5) Please learn common Java nomenclature (naming conventions - e.g. `EachWordUpperCaseClass`, `firstWordLowerCaseMethod()`, `firstWordLowerCaseAttribute` unless it is an `UPPER_CASE_CONSTANT`) and use it consistently. E.G. (the one I noticed) `dialerFrame` should be `DialerFrame`. .. – Andrew Thompson Jun 12 '20 at 03:49
  • .. 6) But having said that, don't extend `JFrame` just use an instance of one, in the same way the code uses plain instances of `JButton` and `JTextField`. 7) As to the task at hand, **use the [`Clip`](https://docs.oracle.com/en/java/javase/13/docs/api/java.desktop/javax/sound/sampled/Clip.html) from [Java Sound](https://docs.oracle.com/javase/tutorial/sound/index.html) to play the WAVS. Or, slightly more complicated, generate the tones in memory at run-time.** – Andrew Thompson Jun 12 '20 at 03:51
  • Ok but how would i import my wav files to be played by any button? And also is there a way to get the tag of a button? I am not talking about the name since I assigned 1 name for 12 buttons since they do the same thing but i need them to play different sounds so is there a method that can get me the printed tag on the button instead of the name. – Beakal Begashaw Jun 12 '20 at 04:37
  • Keep a HashMap of the text of the button and the wav file. – camickr Jun 12 '20 at 13:54

1 Answers1

0

It's a little tricky and IDK how experienced you are with multi-threading.

First off, I would try to use an MVC pattern. You've got the basics of your View portion set up. For the Model, perhaps an enum class makes sense for each number of the phone number, where each enum is associated with an ID, a String for display and an associated Clip (preloaded) or .wav file address (if using SourceDataLine), and maybe a play method.

Then, a critical Control capability is the playback of the phone number, in series, probably within its own thread so that you aren't dead in the water waiting for the sounds to finish playing.

I'd make this controller a class, and have it implement a LineListener and have it respond to Line.EventType.STOP (probably just set a state flag/boolean for a loosely coupled approach) as a way to manage the sequencing and timing of the individual Clip or SourceDataLine plays. (@camickr mentions this in a comment)

I'd also launch the portion that executes the playing of the phone number in its own thread. It can be a private class within the controller class, and thus make reference to the parent class's implementation of the LineListener to check for when to proceed for the "next" sound.

That's the basic floor-plan. There are some details to work out still, but hopefully this will help get you going.

Phil Freihofner
  • 7,645
  • 1
  • 20
  • 41