通过在JComboBox中选择将枚举值传递给函数

时间:2015-04-03 23:46:11

标签: java function enums arguments jcombobox

我只是有一个很棒的主意,但后来我意识到我只是在Java中这么做。我的想法是这样的:

我们有一个名为test(现在)的类,它有一个枚举音 - 你可以看到每个音的频率值。当然我们有getChord()函数来获取这些值。

import javax.swing.*;
import java.awt.*;
import java.util.*;

public class test 
{
public enum Tones
{
    C(261.6), CSHARP(277.2), D(293.7), DSHARP(311.2), E(329.6), F(349.6), FSHARP(370), G(391.9), GSHARP(415.3), A(440), B(466.2), H(493.9);

    private double frequencyVal;

    Tones(double frequencyVal)
    {
        this.frequencyVal = frequencyVal;
    }

    public double getChord()
    {
        return frequencyVal;
    }
    };
}

然后我们有一个名为Chords的类,JComboBox就在这里。我们可以简单地从中选择一个和弦。

import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import javax.swing.*;


class Chords extends JPanel
{
private JComboBox chooseChord = new JComboBox(new String[]{"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "B", "H"});

public Chords() 
{
    chooseChord.setSelectedItem(null);

    chooseChord.addItemListener(new ItemListener() 
    {
        @Override
        public void itemStateChanged(ItemEvent e) 
        {
            Object item = chooseChord.getSelectedItem();

            if ("A".equals(item)) 
            {

            } 

            else if ("B".equals(item)) 
            {

            }

            else if ("H".equals(item)) 
            {

            }

            else if ("C".equals(item)) 
            {

            }

            else if ("C#".equals(item)) 
            {

            }

            else if ("D".equals(item)) 
            {

            }

            else if ("D#".equals(item)) 
            {

            }

            else if ("E".equals(item)) 
            {

            }

            else if ("F".equals(item)) 
            {

            }

            else if ("F#".equals(item)) 
            {

            }

            else if ("G".equals(item)) 
            {

            }

            else if ("G#".equals(item)) 
            {

            }
        }
    });

    add(chooseChord);
}   
}

这就是困难部分的用武之地。我希望我能尽可能简单地描述它。

通过在JComboBox中选择和弦,我想从枚举中选择一组三个特定音调。然后我想将这三个特定值传递给playChord()函数,该函数也在另一个类(代码结束)中。我只是输入频率的随机值。

import java.applet.*;
import java.io.*;
import java.net.*;

import javax.sound.sampled.*;

public final class Audio 
{

    public static final int SAMPLE_RATE = 44100;

    private static final int BYTES_PER_SAMPLE = 2;                // 16-bit audio
    private static final int BITS_PER_SAMPLE = 16;                // 16-bit audio
    private static final double MAX_16_BIT = Short.MAX_VALUE;     // 32,767
    private static final int SAMPLE_BUFFER_SIZE = 4096;

    private static SourceDataLine line;   // to play the sound
    private static byte[] buffer;         // our internal buffer
    private static int bufferSize = 0;    

    private static double amplitude, frequency, phase;

    // not-instantiable
    private Audio() { }

    // static initializer
    static { init(); }

    // open up an audio stream
private static void init() 
{

try 
{
    // 44,100 samples per second, 16-bit audio, mono, signed PCM, little Endian
    AudioFormat format = new AudioFormat((float) SAMPLE_RATE, BITS_PER_SAMPLE, 1, true, false);
    DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

    line = (SourceDataLine) AudioSystem.getLine(info);
    line.open(format, SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE);

    buffer = new byte[SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE/3];
}

catch (Exception e) 
{
    System.out.println(e.getMessage());
    System.exit(1);
}

// no sound gets made before this call
line.start();
}

public void setAmplitude(double a)
{
    amplitude = a;
}

public static void setFrequency(double f)
{
    frequency = f;
}

public void SetPhase(double p)
{
    phase = p;
}

public static double getAmplitude()
{
    return amplitude;
}

public static double getFrequency()
{
    return frequency;
}

public static double getPhase()
{
    return phase;
}

/**
 * Close standard audio.
 */
public static void close() 
{
line.drain();
line.stop();
}

/**
 * Write one sample (between -1.0 and +1.0) to standard audio. If the sample
 * is outside the range, it will be clipped.
 */
public static void play(double in) 
{

// clip if outside [-1, +1]
if (in < -1.0) in = -1.0;
if (in > +1.0) in = +1.0;

// convert to bytes
short s = (short) (MAX_16_BIT * in);
buffer[bufferSize++] = (byte) s;
buffer[bufferSize++] = (byte) (s >> 8);   // little Endian

// send to sound card if buffer is full        
if (bufferSize >= buffer.length) 
{
    line.write(buffer, 0, buffer.length);
    bufferSize = 0;
}
}

/**
 * Write an array of samples (between -1.0 and +1.0) to standard audio. If a     sample
 * is outside the range, it will be clipped.
 */
public static void play(double[] input) 
{
for (int i = 0; i < input.length; i++) 
{
    play(input[i]);
}
}

private static double[] tone(double hz, double duration, double amplitude, double phase) 
{
int N = (int) (Audio.SAMPLE_RATE * duration);
double[] a = new double[N+1];
for (int i = 0; i <= N; i++)
    a[i] = amplitude * Math.sin(2 * Math.PI * i * hz / Audio.SAMPLE_RATE + phase);
return a;
}

public static void playChord() throws LineUnavailableException 
{
double[] a = tone(415.3, 1.0, 1, 0);
double[] b = tone(329.6, 1.0, 1, 0);
double[] c = tone(493.9, 1.0, 1, 0);

for( int i=0; i<a.length; ++ i )
   a[i] = (a[i] + b[i] + c[i]) / 3;

Audio.play(a);
}

public static void playSound() throws LineUnavailableException
{
double[] a = tone(getFrequency(), 1.0, getAmplitude(), getPhase());

for( int i = 0; i < a.length; ++ i )
       a[i] = (a[i]);

Audio.play(a);
}
}

我的程序假设用户可以从列表中选择一个和弦,然后只需按“播放”按钮即可听到它。这就是我希望它自动完成的原因,因为我不确定是否定义了12个单独的函数/存储音调值的变量/数组是最好的方法。

任何线索或帮助如何实现这个复杂的目标?我感到被它淹没了。

编辑: 在我的代码中实现Radiodef的解决方案对我来说有点困难。我想我理解你的代码,但我不能把它实现到我的代码中。你会帮忙吗?我的主要功能如下:

import java.awt.*;
import java.awt.event.*;
import javax.sound.sampled.LineUnavailableException;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.event.*;

import java.awt.*;

public class Window extends JPanel implements ActionListener
{
private JMenuBar mainMenu = new JMenuBar();

private Plot plot = new Plot();
private Parameters param = new Parameters();

private JButton playSound = new JButton("Play");
private JButton getSample = new JButton("Save wave");
private JButton getPlot = new JButton("Save plot");

private Chords music = new Chords();

private JPanel mainPanel = new JPanel();
private JPanel subPanel = new JPanel();
private JPanel buttonsPanel = new JPanel();
private JPanel slidersPanel = new JPanel();

private JLabel chord = new JLabel("Chord:");

private JTextField aValue = new JTextField();
private JTextField fValue = new JTextField(); 
private JTextField pValue = new JTextField();

public Window() 
{
    mainPanel.setLayout(new FlowLayout());
    buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.Y_AXIS));
    slidersPanel.setLayout(new BorderLayout());
    subPanel.setLayout(new BorderLayout());

    buttonsPanel.add(chord);
    buttonsPanel.add(music);
    buttonsPanel.add(Box.createRigidArea(new Dimension(0,10)));
    buttonsPanel.add(playSound);
    buttonsPanel.add(Box.createRigidArea(new Dimension(0,10)));
    buttonsPanel.add(getSample);
    buttonsPanel.add(Box.createRigidArea(new Dimension(0,10)));
    buttonsPanel.add(getPlot);
    buttonsPanel.setBorder(BorderFactory.createTitledBorder("Menu"));

    JMenu langMenu = new JMenu("Language");

    param.addAmplitudeListener(new ChangeListener()
    {
        public void stateChanged(ChangeEvent a)
        {
            int ampValue = param.getAmplitudeValue();
            aValue.setText(String.valueOf(ampValue));
        }
    }
    );


    param.addFrequencyListener(new ChangeListener()
    {
        public void stateChanged(ChangeEvent f)
        {
            double frValue = param.getFrequencyValue();
            fValue.setText(String.valueOf(frValue));
        }
    }
    );


    param.addPhaseListener(new ChangeListener()
    {
        public void stateChanged(ChangeEvent p)
        {
            double phValue = param.getPhaseValue();
            pValue.setText(String.valueOf(phValue));
        }
    }
    );

    playSound.addActionListener(this);
    getPlot.addActionListener(this);
    getSample.addActionListener(this);

    mainMenu.add(langMenu);
    slidersPanel.add(param);
    subPanel.add(buttonsPanel, BorderLayout.NORTH);
    subPanel.add(slidersPanel, BorderLayout.SOUTH);
    mainPanel.add(subPanel);
    mainPanel.add(plot);
    add(mainPanel);


}

public void actionPerformed(ActionEvent a)
{
    Object button = a.getSource();

    if(button==playSound)
        try 
        {
            Audio.playChord(frequencies);
        } 

        catch (LineUnavailableException e) 
        {
            System.out.println("Error");
        }
}

public JMenuBar getmainMenu()
{
    return mainMenu;
}

private static void GUI()
{
    Window mainPanel = new Window();
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(mainPanel);
    frame.setJMenuBar(mainPanel.getmainMenu());
    frame.pack();
    frame.setVisible(true);
    Menu theme = new Menu();
    theme.setVisible(true);
    theme.pack();
}

public static void main(String[] args) 
{
    SwingUtilities.invokeLater(new Runnable() 
    {
         public void run()
         {
            GUI();
         }
      }
      );
}
}

这是我定义按钮actionlisteners的地方。由于到目前为止我的声誉太低而无法发布图片,因此我无法向您展示完整的GUI。发布所有课程将会非常困难。

2 个答案:

答案 0 :(得分:1)

您需要做的一件事是修改playChord方法,使其接受您的频率数组(您以某种方式从用户那里检索到)。您可能会使用以下内容。除了使用数组而不是硬编码的abc之外,这与您已经完成的工作几乎完全相同。

public static void playChord(double[] frequencies)
    throws LineUnavailableException 
{
    double[] buffer = tone(frequencies[0], 1.0, 1, 0);

    for(int i = 1; i < frequencies.length; ++i) {
        double[] harmonic = tone(frequencies[i], 1.0, 1, 0);

        for(int i = 0; i < buffer.length; ++i) {
            buffer[i] += harmonic[i];
        }
    }

    for(int i = 0; i < buffer.length; ++i) {
        buffer[i] /= frequencies.length;
    }

    Audio.play(buffer);
}

所以,继续前进。我不确定你是否意味着用户应该选择一个音符,然后播放和弦的3个相应音符。 (例如,用户选择C来播放主要三位一体的音注CEG。)

tone box

import java.util.*;
import javax.swing.*;
import java.awt.BorderLayout;

class ToneBox implements Runnable {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new ToneBox());
    }

    enum Tone {
        C(261.6),
        CSHARP(277.2),
        D(293.7),
        DSHARP(311.2),
        E(329.6),
        F(349.6),
        FSHARP(370),
        G(391.9),
        GSHARP(415.3),
        A(440),
        ASHARP(466.2), // note: there was an error here
        B(493.9);      // A -> A# -> B, not A -> B -> H

        final double hz;

        Tone(double hz) {
            this.hz = hz;
        }

        double[] triad() {
            List<Tone> values = Arrays.asList(Tone.values());
            double[] chord = new double[3];

            int myIndex = values.indexOf(this);

            // form a triad using the intervals
            // as relative indexes in to the list
            chord[0] = this.hz;
            chord[1] = values.get((myIndex + 4) % values.size()).hz;
            chord[2] = values.get((myIndex + 7) % values.size()).hz;

            return chord;
        }

        // override toString, which JComboBox
        // uses to display, so we can put
        // Tone objects in the box directly

        @Override
        public String toString() {
            return this.name().replace("SHARP", "#");
        }
    }

    @Override
    public void run() {
        final JFrame   frame = new JFrame();
        final JPanel content = new JPanel(new BorderLayout());
        final JComboBox  box = new JComboBox(Tone.values());
        final JButton button = new JButton("Play");

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                // overriding toString makes it much
                // easier for us to retrieve the
                // enum values from the JComboBox

                Tone tone = (Tone)box.getSelectedItem();
                double[] chord = tone.triad();

                JOptionPane.showMessageDialog(null,
                    "Chord selected: " + Arrays.toString(chord)
                );
            }
        });

        content.add(box, BorderLayout.CENTER);
        content.add(button, BorderLayout.SOUTH);

        frame.setContentPane(content);
        frame.pack();
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

如果您的想法是用户单独选择和弦中的音符,您可能还会考虑使用JList进行此类操作。只是一个建议。 JList允许用户选择多个项目。

tone list

import java.util.*;
import javax.swing.*;
import java.awt.BorderLayout;

class ToneList implements Runnable {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new ToneList());
    }

    enum Tone {…} // same as above

    @Override
    public void run() {
        final JFrame   frame = new JFrame();
        final JPanel content = new JPanel(new BorderLayout());
        final JList     list = new JList(Tone.values());
        final JButton button = new JButton("Play");

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                Object[] values = list.getSelectedValues();
                double[] chord  = new double[values.length];

                for(int i = 0; i < chord.length; ++i) {
                    Tone tone = (Tone)values[i];
                    chord[i]  = tone.hz;
                }

                JOptionPane.showMessageDialog(null,
                    "Chord selected: " + Arrays.toString(chord)
                );
            }
        });

        content.add(list, BorderLayout.CENTER);
        content.add(button, BorderLayout.SOUTH);

        frame.setContentPane(content);
        frame.pack();
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

我希望这会给你一些想法来填补你所缺少的东西。

答案 1 :(得分:0)

如果你愿意,你可以让你的枚举成为主类,并让它返回一个用于组合框的字符串列表,有音调和一切。将其视为您的数据库&#34;类。然后让其他人从中请求数据并对值进行操作。

对于&#34;全球&#34;函数(不是特定于枚举的一个实例,例如。&#34; Tones.C.function()&#34;但是&#34; Tones.function()&#34;),使用静态函数。