读书笔记——《Head First Java》MIDI音乐播放器实例

时间:2021-01-04 05:50:10

书的第十一章到十四章

以一个MIDI音乐播放器的例子

穿插了异常处理,图形用户接口,和文件输入输出流的知识


异常处理:

当你调用了有风险的方法时,需要用try/catch来处理

如果自己编写的程序中可能有风险,就要用throw来抛出异常,并且可以抛出多个

try中存放调用方法的语句,然后用catch块做异常处理/恢复程序

有多个catch时,要从继承最底层开始

final语句为无论如何都会执行的部分

一个异常处理代码块中,catch与try中间不能有程序

try一定要含有catch或者final,但只有final要继续抛出异常

如果不想处理异常,暴力的一直throw给java虚拟机,会通过编译,但会产生问题


JAVA的图形界面,awt,swing似乎用的并不多。毕竟是主要用于服务器端语言

大致了解了一些基本方法


还是直接开始实例吧,回顾代码,加上注释

这是运行后的大概样子

读书笔记——《Head First Java》MIDI音乐播放器实例

这个小程序还是很好玩的,可以自己创作乐器伴奏

下面是我自己敲的源码


public class BeatBox {
	
	JPanel mainPanel;
	ArrayList<JCheckBox> checkboxList;
	Sequencer sequencer;
	Sequence sequence;
	Track track;
	JFrame theFrame;
	//存放16种乐器的数组
	String [] instrumentNames = {
			"Bass Drum","Closed Hi-Hat","Open Hi-Hat","Acoustic Snare",
			"Crash Cymbal","Hand Clap","High Tom","Hi Bongo","Maracas",
			"Whistle","Low Conga","Cowbell","Vibraslap","Low-mid Tom",
			"High Agogo","Open Hi  Conga"
	};
	//存放各乐器在MIDI中对应的序号
	int[] instruments = {
			35,42,46,38,49,39,50,60,70,72,64,56,58,47,67,63
	};
	//主方法启动播放器
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		BeatBox beatbox = new BeatBox();
		beatbox.buildGUI();
	}
	//建立用户界面
	public void buildGUI() {
		//主界面的几个模块和初始属性
		theFrame = new JFrame("BeatBox by Yshen");
		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);
		
		JButton save = new JButton("Save");
		save.addActionListener(new MySendListener());
		buttonBox.add(save);
		JButton load = new JButton("Load");
		load.addActionListener(new MyReadInListener());
		buttonBox.add(load);
		//乐器列表
		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(2);
		mainPanel = new JPanel(grid);
		background.add(BorderLayout.CENTER, mainPanel);
		//256个checkbox生成
		for (int i = 0; i < 256; i++) {
			JCheckBox c = new JCheckBox();
			c.setSelected(false);
			checkboxList.add(c);
			mainPanel.add(c);
		}
		
		setUpMidi();
		//设置主界面尺寸并设置为可见
		theFrame.setBounds(50,50,300,300);
		theFrame.pack();
		theFrame.setVisible(true);
		
	}
	//建立MIDI播放器,记得try
	public void setUpMidi () {
		try {
			sequencer = MidiSystem.getSequencer();
			sequencer.open();
			sequence = new Sequence(Sequence.PPQ,4);
			track = sequence.createTrack();
			sequencer.setTempoInBPM(120);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	//track就像歌曲信息
	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;
				}
			}
			
			makeTracks(trackList);
			track.add(makeEvent(176, 1, 127, 0, 16));
		}
		//192为乐器频道
		track.add(makeEvent(192, 9, 1, 0, 15));
		try {
			sequencer.setSequence(sequence);
			sequencer.setLoopCount(sequencer.LOOP_CONTINUOUSLY);
			sequencer.start();
			sequencer.setTempoInBPM(120);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	//144和128频道分别表示开始和结束
	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));
			}
		}
	}
	//MIDIEvent就像乐谱,前四个参数是类型,频道,音符,音量
	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;
	}
	//几个按钮的监听器
	public class MyStartListener implements ActionListener {
		public void actionPerformed (ActionEvent a) {
			buildTrackAndStart();
		}
	}
	
	public class MyStopListener implements ActionListener {
		public void actionPerformed (ActionEvent a) {
			sequencer.stop();
		}
	}
	
	public class MyUpTempoListener implements ActionListener {
		public void actionPerformed (ActionEvent a) {
			float tempoFactor = sequencer.getTempoFactor();
			sequencer.setTempoFactor((float)(tempoFactor * 1.03));
		}
	}
	
	public class MyDownTempoListener implements ActionListener {
		public void actionPerformed (ActionEvent a) {
			float tempoFactor = sequencer.getTempoFactor();
			sequencer.setTempoFactor((float)(tempoFactor * 0.97));
		}
	}
	//这里往下是存取的监听,将256个checkbox序列化存取
	public class MySendListener implements ActionListener {
		public void actionPerformed (ActionEvent a) {
			
			boolean[] checkboxState = new boolean[256];
			for (int i = 0; i < 256; i++) {
				JCheckBox check = (JCheckBox) checkboxList.get(i);
				if (check.isSelected()) {
					checkboxState[i] = true;
				}
			}	
			
			try {
				FileOutputStream fileStream = new FileOutputStream(new File("Checkbox.ser"));
				ObjectOutputStream os = new ObjectOutputStream(fileStream);
				os.writeObject(checkboxState);
				os.close();
				
				
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}
	}
	

	
	public class MyReadInListener implements ActionListener {
		public void actionPerformed (ActionEvent a) {
			
			boolean[] checkboxState = null;
			try {

				FileInputStream fileIn = new FileInputStream(new File("Checkbox.ser"));
				ObjectInputStream is = new ObjectInputStream(fileIn);
				checkboxState = (boolean[]) is.readObject();
				is.close();		

				
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			for (int i = 0; i < 256; i++) {
				JCheckBox check = (JCheckBox) checkboxList.get(i);
				if (checkboxState[i]) {
					check.setSelected(true);
				} else {
					check.setSelected(false);
				}
			}		
			
			sequencer.stop();
			buildTrackAndStart();
			
		}
	}
	

}

可以用这个尝试发布成jar包后转为exe给朋友玩玩。