Java 通过在JComboBox中选择将枚举值传递给函数
我只是有一个很好的想法,但后来我意识到我在Java中太笨了,无法做到这一点。我的想法是这样的:Java 通过在JComboBox中选择将枚举值传递给函数,java,function,enums,arguments,jcombobox,Java,Function,Enums,Arguments,Jcombobox,我只是有一个很好的想法,但后来我意识到我在Java中太笨了,无法做到这一点。我的想法是这样的: 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
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();
}
}
);
}
}
我们有一个名为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;
}
};
}
然后我们有一个名为chord的类,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中选择和弦,我想从enum中选择一组三种特定的音调。然后我想把这三个特定的值传递给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);
}
}
这就是我定义按钮actionlisteners的地方。由于我的声誉太低,目前无法发布图片,所以我无法向您展示完整的GUI。发布所有类太难了。如果愿意,可以将枚举设置为主类,并让它返回用于组合框的字符串列表、音调和所有内容。将其视为“数据库”类。然后让其他人从中请求数据并对值进行操作
对于“全局”函数(不特定于枚举的一个实例,例如“Tones.C.function()”而是“Tones.function()”),请使用静态函数。您需要做的一件事是修改
playChord
方法,以便它接受您的频率数组(您以某种方式从用户处检索到的)。您可以使用如下内容。除了使用数组而不是硬编码的a
、b
和c
之外,这与您已经在做的事情几乎相同
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);
}
如果你的想法是用户单独选择和弦中的音符,你也可以考虑使用A。只是一个建议<代码>JList允许用户选择多个项目
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);
}
}
import java.util.*;
导入javax.swing.*;
导入java.awt.BorderLayout;
类ToneList实现Runnable{
公共静态void main(字符串[]args){
调用器(新的音调列表());
}
枚举音调{…}//同上
@凌驾
公开募捐{
最终JFrame=新JFrame();
最终JPanel内容=新JPanel(新BorderLayout());
最终JList列表=新JList(Tone.values());
最终按钮=新按钮(“播放”);
addActionListener(新建ActionListener()){
@凌驾
已执行的公共无效行动(行动事件ae){
Object[]values=list.getSelectedValues();
double[]chord=新的double[values.length];
对于(int i=0;i
我希望这能给你一些想法来弥补你所缺少的。嗨,非常感谢你的回复。你的第一个例子看起来就像我需要的一样,我马上就要尝试一下。我刚刚发布了我的主要功能。问题是我在那里定义了所有按钮ActionListener。老实说,我们应该在没有Java知识的情况下,在大学里作为一个项目编写这样一个程序。当然,我们有讲座和实验室,但它们太混乱了,我什么都学不到。具体问题是什么?因为在chord类中有一个私有的JComboBox,如果您想在其他地方添加一个动作侦听器,就需要公开它。假设您有一些代码,比如
aButton.addActionListener(new ActionListener(){public void actionPerformed(…){JComboBox=music.getComboBox();…}})
。希望有帮助。如果你需要更多的超出这个问题的原始范围,你可以考虑问一个新问题。
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);
}
}