书的第十一章到十四章
以一个MIDI音乐播放器的例子
穿插了异常处理,图形用户接口,和文件输入输出流的知识
异常处理:
当你调用了有风险的方法时,需要用try/catch来处理
如果自己编写的程序中可能有风险,就要用throw来抛出异常,并且可以抛出多个
try中存放调用方法的语句,然后用catch块做异常处理/恢复程序
有多个catch时,要从继承最底层开始
final语句为无论如何都会执行的部分
一个异常处理代码块中,catch与try中间不能有程序
try一定要含有catch或者final,但只有final要继续抛出异常
如果不想处理异常,暴力的一直throw给java虚拟机,会通过编译,但会产生问题
JAVA的图形界面,awt,swing似乎用的并不多。毕竟是主要用于服务器端语言
大致了解了一些基本方法
还是直接开始实例吧,回顾代码,加上注释
这是运行后的大概样子
这个小程序还是很好玩的,可以自己创作乐器伴奏
下面是我自己敲的源码
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给朋友玩玩。