• 如何使用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);

     

     

  • 相关阅读:
    Apache-Shiro分布式环境配置(与redis集成)(转)
    springboot整合mybatis将sql打印到日志(转)
    springboot中logback打印日志(转)
    Spring Boot Junit单元测试
    玩转Spring Boot 自定义配置、导入XML配置与外部化配置
    Windows开机自启动位置
    木马开机启动的六种方法(记录)
    用Delphi开发视频聊天软件
    Delphi用Socket API实现路由追踪
    前端工程师应该都了解的16个最受欢迎的CSS框架
  • 原文地址:https://www.cnblogs.com/lujun1949/p/6248728.html
Copyright © 2020-2023  润新知