欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

gridbagconstraints布局(gridbaglayout布局管理器的用法)

程序员文章站 2023-12-09 16:43:51
前几次博客中也是用java实现录音机的各种功能,这次是比先前有了一点优化,将录音的功能单独提取出来,这个程序的实现用到了编码器lame.exe这个的作用是将录音得到的wav文件编码成mp3文件,这样的...

前几次博客中也是用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;
}
}
}
}

}