gridbaglayout布局管理器的用法,gridbagconstraints布局

前幾次博客中也是用java實現錄音機的各種功能,這次是比先前有了一點優化,將錄音的功能單獨提取出來,這個程序的實現用到了編碼器LAME.exe這個的作用是將錄音得到的wav文件編碼成MP3文件,這樣的結果是容量大大減少,因為LAME編碼器經測試在編碼過程中路徑中帶有空格問題未能解決,所以只能找了一個笨的方法,為了將其放到指定的文件夾下(這個文件夾路徑是帶有空格的),所以只能先存放到D盤,然後利用文件操作將其複製到指定的路徑下,然後再刪除,程序中還用到了圖片,修改了java的圖標,所以在運行時可將其注釋掉,寫的很爛,相互學習哈!

/*
* 實現錄音機的功能
* 1.在原來的基礎上界面更加精簡,字體變大使用戶更加方便
* 2.在停止錄音後便直接保存為.mp3文件
* 3.對停止錄音進行改進,將錄音按鈕設計成類似微信的形式,按下時進行錄音,鬆開即停止錄音並保存即可
* 4.在錄音的時候在面板上顯示音頻波,表示正在錄音
*/
package com.liuyun.MyRecord6;

import java.awt.*;

import javax.swing.*;
import java.awt.event.*;
import java.io.*;

import javax.sound.sampled.*;

import java.lang.*;

public class MyRecord6 extends JFrame implements MouseListener{

//定義錄音格式
AudioFormat af = null;
//定義目標數據行,可以從中讀取音頻數據,該 TargetDataLine 介面提供從目標數據行的緩衝區讀取所捕獲數據的方法。
TargetDataLine td = null;
//定義源數據行,源數據行是可以寫入數據的數據行。它充當其混頻器的源。應用程序將音頻位元組寫入源數據行,這樣可處理位元組緩衝並將它們傳遞給混頻器。
SourceDataLine sd = null;
//定義位元組數組輸入輸出流
ByteArrayInputStream bais = null;
ByteArrayOutputStream baos = null;
//定義音頻輸入流
AudioInputStream ais = null;
//定義停止錄音的標誌,來控制錄音線程的運行
Boolean stopflag = false;
//記錄開始錄音的時間
long startPlay;
//設置一個播放的標誌
Boolean playflag;
//每次保存的最後的文件名
File tarFile = null;
//定義音頻波形每次顯示的位元組數
int intBytes = 0;
//定義每次錄音的時候每次提取位元組來畫音頻波
byte audioDataBuffer[] = null;
//定義所需要的組件
JPanel jp1,jp2,jp3;
JLabel jl1=null;
JButton captureBtn;
//設置畫波形線程的終止的標誌
boolean flag = true;
//定義播放錄音時的一個計數值
int cnt;
//定義播放錄音時一個緩衝數組
byte btsPlay[] = null;

int gridx, gridy, gridwidth, gridheight, anchor, fill, ipadx, ipady;
double weightx, weighty;
Insets inset;
GridBagConstraints c;

public static void main(String[] args) {

//創造一個實例
MyRecord6 mr = new MyRecord6();

}
//構造函數
public MyRecord6()
{
//組件初始化
jp1 = new JPanel();
jp2 = new JPanel();
jp3 = new JPanel();

//定義jp1的字體
Font jpFont = new Font(“華文新魏”,Font.BOLD,40);
jl1 = new JLabel(“請留下您想說的話”);
jl1.setFont(jpFont);
jl1.setForeground(Color.red);
jp1.add(jl1);
//定義按鈕上面的字體
Font btFont = new Font(“華文新魏”,Font.BOLD,40);
captureBtn = new JButton(“按住 說話”);
//setForeground可以設置按鈕上面字體的顏色
captureBtn.setForeground(Color.RED);
captureBtn.setFont(btFont);
//對開始錄音按鈕進行滑鼠監聽
captureBtn.addMouseListener(this);

this.add(jp1,BorderLayout.NORTH);
this.add(jp2,BorderLayout.CENTER);
this.add(jp3,BorderLayout.SOUTH);
GridBagLayout gridbag = null;
jp3.setLayout(gridbag = new GridBagLayout());
gridx=1;
gridy=2;
gridwidth=1;
gridheight=1;
weightx=1;
weighty=1;
anchor=GridBagConstraints.CENTER;
fill=GridBagConstraints.HORIZONTAL;
inset=new Insets(1,1,1,1);
ipadx=0;
ipady=30;
c = new GridBagConstraints(gridx, gridy, gridwidth, gridheight,
weightx, weighty, anchor, fill, inset, ipadx, ipady);
gridbag.setConstraints(captureBtn, c);
jp3.add(captureBtn);

//設置窗口的屬性
this.setSize(800,500);
this.setTitle(“錄音機”);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//設置窗口居中
this.setLocationRelativeTo(null);
//將窗口的邊框去掉
this.setUndecorated(true);
this.setVisible(true);
//設置窗口上的圖標
Image img = this.getToolkit().getImage(getClass().getResource(“/image/Recorder.jpg”));
this.setIconImage(img);
//設置窗口在最前端顯示
this.setAlwaysOnTop(true);
}
public void mouseClicked(MouseEvent e) {

}
public void mousePressed(MouseEvent e) {
//當開始錄音按鈕被按下時就開始錄音
if(e.getSource().equals(captureBtn))
{
//改變按鈕上面的字的內容
captureBtn.setText(“鬆開 結束”);

//調用錄音的方法
capture();

//記錄開始錄音的時間
startPlay = System.currentTimeMillis();
}

}

public void mouseReleased(MouseEvent e) {
//當鬆開錄音按鈕時停止錄音並保存錄音的文件
if(e.getSource().equals(captureBtn))
{
//調用停止錄音的方法
stop();
//當鬆開按鈕後對顯示波形的面板進行清空
jp2.repaint();
//改變按鈕上面的字的內容
captureBtn.setText(“按住 說話”);
//調用保存錄音的方法
save();
//將其放到指定的路徑下
//定義最終要存放的文件路徑
String destPath = “D:/Program Files/apache-tomcat-6.0.35/webapps/XWZ/tempFile/”;
copyFile(“D:/”+tarFile.getName(), destPath);

System.exit(0);
}
}

public void mouseEntered(MouseEvent e) {

}
public void mouseExited(MouseEvent e) {

}
//開始錄音
public void capture()
{
try {
//af為AudioFormat也就是音頻格式
af = getAudioFormat();
DataLine.Info info = new DataLine.Info(TargetDataLine.class,af);
td = (TargetDataLine)(AudioSystem.getLine(info));

//打開具有指定格式的行,這樣可使行獲得所有所需的系統資源並變得可操作。
td.open(af);
//允許某一數據行執行數據 I/O
td.start();

//啟動顯示波形的進程
RecordWave aw = new RecordWave();
Thread t2 = new Thread(aw);
t2.start();
//把顯示波形的進程標誌設為true
flag = true;

Record record = new Record();
Thread t1 = new Thread(record);
t1.start();
} catch (Exception ex) {
ex.printStackTrace();
return;
}
}
//停止錄音
public void stop()
{
stopflag = true;
//將畫波形的進程終止
flag = false;
}
//保存錄音
public void save()
{
af = getAudioFormat();
byte audioData[] = baos.toByteArray();
bais = new ByteArrayInputStream(audioData);
ais = new AudioInputStream(bais,af, audioData.length / af.getFrameSize());
//定義最終保存的文件名
File file = null;
//寫入文件
try {
//以當前的時間命名錄音的名字
//將錄音的文件存放到F盤下語音文件夾下
File filePath = new File(“D:/AudioFile”);
String tarPath = “D:/”;
if(!filePath.exists())
{//如果文件不存在,則創建該目錄
filePath.mkdirs();
}
long time = System.currentTimeMillis();
file = new File(filePath+”/”+time+”.wav”);
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, file);
//將錄音產生的wav文件轉換為容量較小的mp3格式
//定義產生後文件名
tarFile = new File(tarPath+time+”.mp3″);
Runtime run = null;
//測試當前的路徑

try {
run = Runtime.getRuntime();
//調用編碼器來將wav文件轉換為mp3文件
//把編碼得到的mp3文件先存放到D盤下,然後利用文件拷貝函數將它放到指定的文件夾下同時將D盤下的文件刪除
Process p=run.exec(filePath+”/”+”lame -b 16 “+filePath+”/”+file.getName()+” “+tarPath+tarFile.getName()); //16為碼率,可自行修改
//釋放進程
p.getOutputStream().close();
p.getInputStream().close();
p.getErrorStream().close();
//等待
p.waitFor();

// //刪除之前保存的的wav文件
// if(file.exists())
// {
// file.delete();
// }

// //定義最終要存放的文件路徑
// String destPath = “D:/Program Files/apache-tomcat-6.0.35/webapps/XWZ/tempFile/”;
// copyFile(tarPath+tarFile.getName(), destPath);
} catch (Exception e) {
e.printStackTrace();
}finally{
//最後都要執行的語句
//run調用lame解碼器最後釋放內存
run.freeMemory();
}

} catch (Exception e) {
e.printStackTrace();
}finally{
//關閉流
try {

if(bais != null)
{
bais.close();
}
if(ais != null)
{
ais.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//文件拷貝方法
public void copyFile(String srcPath , String destPath)
{
File srcFile = new File(srcPath);
//如果目的文件夾沒有則創建目的文件夾
(new File(destPath)).mkdirs();
//在目的文件夾下創建要複製的文件
File destFile = new File(destPath+”/”+srcFile.getName());
if(srcFile.isFile() && srcFile.exists())
{
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(srcFile);
out = new FileOutputStream(destFile);
//設置緩衝數組
byte[] buff = new byte[1024*5];
int len = 0;
while ((len = in.read(buff)) != -1)
{
out.write(buff, 0, len);
}
// //測試該函數是否執行
// System.out.println(“ok1”);

} catch(Exception e) {
e.printStackTrace();
}finally{
//關閉流,先開的後關閉
try {
if(out != null)
{
out.close();
}
if(in != null)
{
in.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//複製過後刪除源文件夾中的的文件
if(srcFile.exists())
{
srcFile.delete();
}
}
//設置AudioFormat的參數
public AudioFormat getAudioFormat()
{
//下面注釋部分是另外一種音頻格式,兩者都可以
AudioFormat.Encoding encoding = AudioFormat.Encoding.
PCM_SIGNED ;
float rate = 8000f;
int sampleSize = 16;
String signedString = “signed”;
boolean bigEndian = true;
int channels = 1;
return new AudioFormat(encoding, rate, sampleSize, channels,
(sampleSize / 8) * channels, rate, bigEndian);
// //採樣率是每秒播放和錄製的樣本數
// float sampleRate = 16000.0F;
// // 採樣率8000,11025,16000,22050,44100
// //sampleSizeInBits表示每個具有此格式的聲音樣本中的位數
// int sampleSizeInBits = 16;
// // 8,16
// int channels = 1;
// // 單聲道為1,立體聲為2
// boolean signed = true;
// // true,false
// boolean bigEndian = true;
// // true,false
// return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed,bigEndian);
}
//錄音類,因為要用到MyRecord類中的變數,所以將其做成內部類
class Record implements Runnable
{
//定義存放錄音的位元組數組,作為緩衝區
byte bts[] = new byte[10000];
//將位元組數組包裝到流里,最終存入到baos中
//重寫run函數
public void run() {
baos = new ByteArrayOutputStream();
try {
stopflag = false;
while(stopflag != true)
{
//當停止錄音沒按下時,該線程一直執行
//從數據行的輸入緩衝區讀取音頻數據。
//要讀取bts.length長度的位元組,cnt 是實際讀取的位元組數
int cnt = td.read(bts, 0, bts.length);
if(cnt > 0)
{
baos.write(bts, 0, cnt);
}

//開始從音頻流中讀取位元組數
byte copyBts[] = bts;
bais = new ByteArrayInputStream(copyBts);
ais = new AudioInputStream(bais, af, copyBts.length/af.getFrameSize());
try{
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, af);
sd = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
sd.open(af);
sd.start();

//從音頻流中讀取
int Buffer_Size = 10000;
audioDataBuffer = new byte[Buffer_Size];
int outBytes;

intBytes = ais.read(audioDataBuffer, 0,audioDataBuffer.length);

// 不寫到混頻器中這樣就不會播放
// if (intBytes >= 0) {
// outBytes = sd.write(audioDataBuffer, 0,audioDataBuffer.length);
// }
}catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
//intBytes = -1;
//關閉打開的位元組數組流
if(baos != null)
{
baos.close();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//下面這句td.drain()不能要,這樣如果不播放數據就阻塞再次錄音會出現其他程序訪問錯誤
//td.drain();
td.close();
//刷新顯示波形的面板
jp2.repaint();
}
}
}

}

//畫波形的類
//因為要使用一些主函數中的數據,所以做成內部類
class RecordWave extends JPanel implements Runnable
{
//用畫筆畫出波形
public void paint(Graphics g)
{
super.paint(g);
g.fillRect(jp2.getX(),jp2.getY() , 800, 380);
if( audioDataBuffer != null)
{
g.drawLine(jp2.getWidth() / 256, 700, jp2.getWidth() / 256, 700);

for(int i=0; i<audioDataBuffer.length-1; ++i)
{
g.setColor(Color.RED);
g.drawLine(i * jp2.getWidth() / 256, (int)audioDataBuffer[i]+200 , (i + 1)

* jp2.getWidth() / 256, (int)audioDataBuffer[i+1]+200);
}
}
}
public void run()
{
//刷新波形
while(true)
{
//System.out.println(“ok”);
try {
synchronized (this) {
//隔多長時間獲取
Thread.sleep(300);
}
} catch (Exception e) {

e.printStackTrace();
}
this.paint(jp2.getGraphics());
//終止線程
if(flag == false)
{
break;
}
}
}
}

}

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/233177.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-11 13:25
下一篇 2024-12-11 13:25

相關推薦

發表回復

登錄後才能評論