程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 如何使用swing創建一個BeatBox,swing創建beatbox

如何使用swing創建一個BeatBox,swing創建beatbox

編輯:JAVA綜合教程

如何使用swing創建一個BeatBox,swing創建beatbox


首先,我們需要回顧一些內容(2017-01-04 14:32:14):

       1.Swing組件

      Swing的組件(component,或者稱之為元件),是較widget更為正確的術語,它們就是會放在GUI(Graphical User Interface)上面的東西,這些內容就是一些用戶會看到並且與其交互的,如Text Field、Button、scrollable、list、radio button等,這些組件均是繼承自java.swing.JComponent;

      在Swing中,幾乎所有的組件都是安置到其他組件當中。

     2.創建GUI的四個步驟:

  • 創建window(JFrame)

 1 JFrame frame=new JFrame(); 

  • 創建組件

1 JButton button=new JButton(“click me”);

  • 將組件添加到frame上

1 frame.getContentPane.add(BorderLayout.EAST,button);

  • 顯示出來

 1 frame.setSize(300,300);

2 frame.setVisible(true); 

3.布局管理器(layout Managers)

首先,布局管理器是與特定組件相關聯的java對象,他大多數是背景組件。

其次,布局管理器是用來控制所關聯組件上攜帶的其他組件,換言之,如果某個框架帶有面板,面板上有按鈕的情況下,則面板布局管理器就是控制按鈕的大小與位置,而框架的布局管理器是控制著面板的大小與位置。

將對應的按鍵添加到對應的面板上,可以如下實現:

 1 JPanel jpanel=new JPanel();   

2 JButton button=new JButton(“click me”);

3 jpanel.add(button); 

4.三大首席管理器:

  • border
  • flow
  • box

    1)BorderLayout:該管理器會將組建分割成5個區域,每個區域只能放置一個組件,由此管理員安置的組件不會取得默認的大小。這個也是框架默認得布局管理器;

    2)FlowLayout:該管理器的行為與文書處理程序的版面配置方式差不多。這個組件會依照理想的大小呈現,並且胡依照從左到右,依次加入的順序(中間可能會換行)排列,因此如果組建放不下一行的時候會自動換行。這個是面板默認得布局管理器。

    3)BoxLayout:它就像FlowLayout一樣讓每個組件按照默認得大小,依次按照加入的順序進行排列,它是以垂直的方式排列(也可以水平,但是通常我們只關心垂直的方式)。與FlowLayout不 同的是,它是需要插入某種換行的機制來強制組件從新的一列進行排列。

     接下來我們看一下干貨:    

3 import java.awt.BorderLayout;
  4 import java.awt.GridLayout;
  5 import java.awt.Label;
  6 import java.awt.event.ActionEvent;
  7 import java.awt.event.ActionListener;
  8 import java.util.ArrayList;
  9 
 10 import javax.sound.midi.*;
 11 import javax.swing.*;
 12 
 13 public class BeatBox {
 14     JPanel mainJPanel;
 15     ArrayList<JCheckBox> checkboxslist;
 16     Sequencer sequencer;
 17     Sequence sequence;
 18     Track track;
 19     JFrame theFrame;
 20     String[]instrumentNames={
 21             "Bass Drum","closed Hi-Hat","open Hi-Hat","Acoustic Snare",
 22             "Crash Cymbal","Hand Clap","High Tome","Hi Bongo","Maracas",
 23             "Whistal","Low Conga","Cowbell","Vibraslap","Low_mid Tom",
 24             "High Agogo","open High Coga"
 25     };//樂器的名稱,用String的array維護
 26     int []instrument={35,42,46,38,49,39,50,60,70,72,64,56,58,47,67,63};//實際樂器的關鍵字,比如說35是Bass Drum,42是closed Hi-Hat
 27     public static void main(String[] args) {
 28         // TODO Auto-generated method stub
 29        new BeatBox().buildGUI();
 30     }
 31     public void buildGUI(){
 32         theFrame = new JFrame("Cyber BeatBox");
 33         theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗口關閉時關閉程序
 34         BorderLayout layout = new BorderLayout();//定義了一個BorderLayout面板對象
 35         JPanel background=new JPanel(layout);//將面板對象實例化JPanel對象
 36         background.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));//用於設置邊緣空白大小
 37         
 38         checkboxslist=new ArrayList<JCheckBox>();
 39         Box buttonBox = new Box(BoxLayout.Y_AXIS);        
 40         
 41         JButton start = new JButton("start");
 42         start.addActionListener(new MyStartlistener());
 43         buttonBox.add(start);
 44         
 45         JButton stop = new JButton("stop");
 46         start.addActionListener(new MyStoplistener());
 47         buttonBox.add(stop);
 48         
 49         JButton upTempo = new JButton("Tempo up");
 50         start.addActionListener(new MyupTempolistener());
 51         buttonBox.add(upTempo);
 52         
 53         JButton downTempo = new JButton("Tempo down");
 54         start.addActionListener(new MydownTempolistener());
 55         buttonBox.add(downTempo);
 56         
 57         Box nameBox=new Box(BoxLayout.Y_AXIS);
 58         for(int i=0;i<16;i++){
 59             nameBox.add(new Label(instrumentNames[i]));
 60         }
 61         
 62         background.add(BorderLayout.EAST,buttonBox);
 63         background.add(BorderLayout.WEST,nameBox);
 64         
 65         theFrame.getContentPane().add(background);
 66         
 67         GridLayout gridLayout=new GridLayout(16,16);//創建具有指定行數和列數的網格布局。 布局中的所有組件都具有相等的大小。
 68                                            //行和列中的一個(但不是兩者)可以為零,這意味著任何數量的對象都可以放置在一行或一列中。
 69         gridLayout.setVgap(1);//將組件之間的垂直間距設置為指定的值。
 70         gridLayout.setHgap(2);//將組件之間的水平間距設置為指定的值。
 71         mainJPanel=new JPanel(gridLayout);
 72         background.add(BorderLayout.CENTER,mainJPanel);
 73         
 74         for(int i=0;i<256;i++){
 75             JCheckBox checkBox=new JCheckBox();
 76             checkBox.setSelected(false);
 77             checkboxslist.add(checkBox);
 78             mainJPanel.add(checkBox);
 79         }//結束循環
 80         //創建checkBox組,並將其設定成未勾選的false,並添加到arraylist以及面板上
 81         
 82         setUpMidi();
 83         
 84         theFrame.setBounds(50, 50, 300, 300);
 85         theFrame.pack();//pack()函數:使此窗口的大小適合其子組件的首選大小和布局。 如果任一維度小於由上次調用setMinimumSize方法指定的最小大小,則會自動放大窗口的最終寬度和高度。
 86                           //如果窗口和/或其所有者不可顯示,則在計算優選大小之前使它們兩者都可顯示。 窗口在計算其大小後生效。
 87         theFrame.setVisible(true);
 88     }//關閉buildGUI()方法
 89     
 90     public void setUpMidi(){
 91         try{
 92             
 93             sequencer= MidiSystem.getSequencer();//此方法等效於調用getSequencer(true) 創建sequencer
 94             sequencer.open();
 95             //創建並打開隊列
 96             
 97             sequence=new Sequence(Sequence.PPQ, 4);
 98             track=sequence.createTrack();
 99             //創建隊列並track
100             
101             sequencer.setTempoInBPM(120);
102             
103         }catch(Exception e){
104             e.printStackTrace();
105         }
106     }//關閉 setUpMidi()方法
107     
108     public void buildTrackAndStart(){
109         
110         int []trackList=null;//創建出16個元素的數組來存儲一項樂器值,如果有該演奏,其值就將會是關鍵字值,否則將值為零
111         
112         sequence.deleteTrack(track);        
113         track=sequence.createTrack();//清除舊的track,做一個新的
114         
115         for (int i = 0; i < 16; i++) {//每個樂器執行一次
116             trackList=new int[16];
117             
118             int key=instrument[i];//設代表樂器的關鍵字
119             
120             for(int j = 0;j<16;j++){//每一拍執行一次
121                 JCheckBox jc=(JCheckBox)checkboxslist.get(j+16*i);
122                 if(jc.isSelected()){//如果勾選,那麼關鍵字的值放到數組得該位置上,不然的話,就補零
123                     trackList[j]=key;
124                 }else{
125                     trackList[j]=0;
126                 }
127             }//關閉循環
128             
129             makeTracks(trackList);
130             track.add(makeEvent(176,1,127,0,16));//創建此樂器事件,並添加到track上;
131         }//關閉外循環
132         
133         
134         track.add(makeEvent(192,9,1,0,15));
135         
136         try{
137             sequencer.setSequence(sequence);
138             sequencer.setLoopCount(sequencer.LOOP_CONTINUOUSLY);
139             sequencer.start();
140             sequencer.setTempoInBPM(120);//以每分鐘的拍數設置速度。 播放的實際速度是指定值和速度因子的乘積。
141         }catch(Exception e){
142             e.printStackTrace();
143         }
144     }//結束buildTrackAndStart方法
145     
146     public class MyStartlistener implements ActionListener{
147         //按鈕的監聽者
148         @Override
149         public void actionPerformed(ActionEvent e) {
150             // TODO Auto-generated method stub
151             buildTrackAndStart();
152         }
153         
154     }//內部類關閉
155     public class MyStoplistener implements ActionListener{
156         //按鈕的監聽者
157         @Override
158         public void actionPerformed(ActionEvent e) {
159             // TODO Auto-generated method stub
160             sequencer.stop();
161         }
162         
163     }//內部類關閉
164     public class MyupTempolistener implements ActionListener{
165         //按鈕的監聽者
166         @Override
167         public void actionPerformed(ActionEvent e) {
168             // TODO Auto-generated method stub
169             float tempoFactor=sequencer.getTempoFactor();
170             sequencer.setTempoFactor((float)(tempoFactor*1.03));//節奏因子,預設為1.0,每次調整3%
171         }
172         
173     }//內部類關閉
174     public class MydownTempolistener implements ActionListener{
175         //按鈕的監聽者
176         @Override
177         public void actionPerformed(ActionEvent e) {
178             // TODO Auto-generated method stub
179             float tempoFactor=sequencer.getTempoFactor();
180             sequencer.setTempoFactor((float)(tempoFactor*.97));//節奏因子,預設為1.0,每次調整3%
181         }
182         
183     }//內部類關閉
184     public void makeTracks(int []list){
185         
186         for (int i = 0; i < 16; i++) {
187             int key=list[i];
188             if (key!=0) {
189                 track.add(makeEvent(144,9,key,100,i));
190                 track.add(makeEvent(128,9,key,100,i+1));//創建Note on以及Note off,並添加到track上
191             }
192         }
193     }//關閉makeTracks方法
194     public MidiEvent makeEvent(int comd,int chan,int one,int two,int tick){
195          MidiEvent event=null;
196          try{
197              ShortMessage shortMessage=new ShortMessage();//創建消息實例
198              shortMessage.setMessage(comd, chan, one, two);//調用setMessage
199              event=new MidiEvent(shortMessage, tick);//制作消息的MidiEvent實例
200          }catch(Exception e){
201              e.printStackTrace();
202          }
203         return event;
204     }//關閉makeEvent方法,該方法是制作消息以及事件
205 }

 

   對應的界面呈現為:

    

問:框架為什麼不能像面板那樣直接加上組件呢?

      答:JFrame會這麼特殊是因為它是讓無顯示在畫面上的接點。

      因為Swing的組件純粹是由Java構成的,JFrame必須要連接到底層的操作系統以便於存儲顯示裝置。我們可以把面板想做是安置在JFrame上的100%的java層,或者把JFrame想作是支撐面板的框架,他甚至可以使用 自定義的方式換掉框架的面板: 

1  nyframe.setContentpane(myPanel);

 

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved