为音乐合成器创建GUI时出现Null Exception

时间:2015-01-06 20:27:27

标签: java

我正在尝试从Head First Java重现代码,在那里他们为节拍框创建API。我一直得到一个null异常,但我不知道为什么。有人有想法吗? (null异常来自buildTrackAndStart()中的音序器。

import java.awt.*;
import javax.swing.*;
import javax.sound.midi.*;
import java.util.*;
import java.awt.event.*;

public class BeatBox {

  JPanel mainPanel;
  ArrayList<JCheckBox> checkboxList;
  Sequencer sequencer;
  Sequence sequence;
  Track track;
  JFrame theFrame;

  String[] instrumentNames = {"Bass Drum", "Closed Hi-Hat", 
          "Open Hit-Hat", "Acoustic snare", "Crash Cymbal", "Hand Clap",
          "High Tom", "High Bongo", "Maracas", "Whistle", "Low Conga",
          "Cowbell", "Vibraslap", "Low-mid Tom", "High Agogo", 
          "Open Hi Conga"};
  int[] instruments = {35, 42, 46, 38, 49, 39, 50, 60, 70, 72, 64, 56, 58, 47, 67, 63};

  public static void main(String[] args){
    new BeatBox().buildGui();
  }

  public void buildGui(){
    theFrame = new JFrame("Cyber beat box");
    theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    BorderLayout layout = new BorderLayout();
    JPanel background = new JPanel(layout);
    background.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));

    checkboxList = new ArrayList<JCheckBox>();
    Box buttonBox = new Box(BoxLayout.Y_AXIS);

    JButton start = new JButton("Start");
    start.addActionListener(new MyStartListener());
    buttonBox.add(start);

    JButton stop = new JButton("Stop");
    stop.addActionListener(new MyStopListener());
    buttonBox.add(stop);

    JButton upTempo = new JButton("Tempo up");
    upTempo.addActionListener(new MyUpTempoListener());
    buttonBox.add(upTempo);

    JButton downTempo = new JButton("Tempo down");
    downTempo.addActionListener(new MyDownTempoListener());
    buttonBox.add(downTempo);

    Box nameBox = new Box(BoxLayout.Y_AXIS);
    for (int i = 0; i < 16; i++){
      nameBox.add(new Label(instrumentNames[i]));
    }

    background.add(BorderLayout.EAST, buttonBox);
    background.add(BorderLayout.WEST, nameBox);

    theFrame.getContentPane().add(background);

    GridLayout grid = new GridLayout(16, 16);
    grid.setVgap(1);
    grid.setHgap(1);

    mainPanel = new JPanel(grid);
    background.add(BorderLayout.CENTER, mainPanel);

    for (int i = 0; i < 256; i++){
      JCheckBox c = new JCheckBox();
      c.setSelected(false);
      checkboxList.add(c);
      mainPanel.add(c);
    } // end loop

    setUpMidi();

    theFrame.setBounds(50, 50, 300, 300);
    theFrame.pack();
    theFrame.setVisible(true);
  } // close method

  public void setUpMidi(){
    try{
      Sequencer sequencer = MidiSystem.getSequencer();
      System.out.println("in setup sequencer == null " + (sequencer == null));
      sequencer.open();
      sequence = new Sequence(Sequence.PPQ, 4);
      track = sequence.createTrack();
      sequencer.setTempoInBPM(120);

    } catch(Exception e){
      e.printStackTrace();
    }
  } // close method

  public void buildTrackAndStart(){
    int[] trackList = null;


    sequence.deleteTrack(track);
    track = sequence.createTrack();

    for (int i = 0; i < 16; i++){
      trackList = new int[16];

      int key = instruments[i];

      for (int j = 0; j < 16; j++){
        JCheckBox jc = (JCheckBox) checkboxList.get(j + (16*i));

        if (jc.isSelected()){
          trackList[j] = key;
        }
        else{
          trackList[j] = 0;
        }
      } // close inner loop 

      makeTracks(trackList);
      track.add(makeEvent(176, 1, 127, 0, 16));
    } // close outer loop

    track.add(makeEvent(192, 9, 1, 0, 15));

    try{
      System.out.println("sequencer == null " + (sequencer == null));
      sequencer.setSequence(sequence);
      sequencer.setLoopCount(sequencer.LOOP_CONTINUOUSLY);
      sequencer.start();
      sequencer.setTempoInBPM(120);
    } catch (Exception e){
      e.printStackTrace();
    }
  } // close buildTrackAndStart method

  public class MyStartListener implements ActionListener {
    public void actionPerformed(ActionEvent a){
      buildTrackAndStart();
    }
  } // close inner class

  public class MyStopListener implements ActionListener{
    public void actionPerformed(ActionEvent a){
      sequencer.stop();
    }
  } // close inner class

  public class MyUpTempoListener implements ActionListener{
    public void actionPerformed(ActionEvent a){
      float tempoFactor = sequencer.getTempoFactor();
      sequencer.setTempoFactor((float) (tempoFactor * 1.03));
    }
  } // close inner class

  public class MyDownTempoListener implements ActionListener{
    public void actionPerformed(ActionEvent a){
      float tempoFactor = sequencer.getTempoFactor();
      sequencer.setTempoFactor((float) (tempoFactor * .97));
    }
  } // close inner class

  public void makeTracks(int[] list){
    for (int i = 0; i < 16; i++){
      int key = list[i];

      if (key != 0){
        track.add(makeEvent(144, 9, key, 100, i));
        track.add(makeEvent(128, 9, key, 100, i+1));
      }
    }    
  } // close makeTracks method

  public MidiEvent makeEvent(int comd, int chan, int one, int two, int tick){
    MidiEvent event = null;
    try{
      ShortMessage a = new ShortMessage();
      a.setMessage(comd, chan, one, two);
      event = new MidiEvent(a, tick);
    } catch (Exception e){
      e.printStackTrace();
    }

    return event;
  }

}

1 个答案:

答案 0 :(得分:2)

setUpMidi中,您声明了一个局部变量sequencer并对其进行了初始化。但这并不会影响您所隐藏的变量,即在类顶部声明的实例变量sequencer,因此它仍为null。变化

Sequencer sequencer = MidiSystem.getSequencer();

sequencer = MidiSystem.getSequencer();

所以它没有声明另一个变量,所以它引用了实例变量。