快捷搜索:

用Java构造自己的媒体播放器

一、概述

首先我们来看看构造这个媒体播放器要达到什么样的目标,确定了目标也就确定了代码量和法度榜样的繁杂程度。本文的媒体播放器要达到如下目标:

媒体播放器是一个菜单驱动的简单AWT利用。

媒体播放器包孕一个“文件”菜单,文件菜单包孕三个菜单项:

“打开”,用来打开媒体文件。

“轮回”,是播放一次(默认),照样重复播放。

“退出”,退出法度榜样。

媒体播放器可以在多种平台上运行。

媒体播放器的核心功能经由过程JMF(Java Media Framework)API实现。JMF扩展了J2SE平台的多媒体能力,容许Java利用和Applet截取、回放、转换包括音频和视频在内的多种媒体。JMF支持多种媒体款式,详细请拜见Supported Media Formats and Capture Devices。

二、初步设计

我们把这个媒体播放器的设计分成两个部分:GUI设计,伪代码设计。在GUI设计中,我们要懂得构成法度榜样的各个GUI部件。在伪代码设计中,我们用自然说话写出法度榜样运行道理。

2.1 GUI设计

媒体播放器的用户界面包孕一个主窗口、一个菜单和一个打开文件的对话框。首先我们来看看主窗口的设计。主窗口应该把窗口标题显示为“媒体播放器1.0”,显示“文件”菜单,显示彩色背景的“迎接”信息。图一显示了法度榜样刚启动时的主窗口。

screen.width-333)this.width=screen.width-333;">

图一:媒体播放器的主窗口

“文件”菜单包孕三个菜单项。“打开”菜单显示一个对话框,用来选择媒体文件的位置。“轮回”菜单抉择媒体文件只播放一次(默认)照样反复播放(当菜单当选中)。着末,“退出”菜单关闭法度榜样。别的,点击主窗口右上角的关闭按钮也可以关闭法度榜样。请拜见图二。

screen.width-333)this.width=screen.width-333;">

图二:“文件”菜单

点击“文件/打开”菜单时,“打开媒体文件”对话框呈现。选中媒体文件之后,点击“打开”按钮即可打开媒体文件;点击“取消”按钮中止文件打开操作。如图三所示。

screen.width-333)this.width=screen.width-333;">

图三:“打开媒体文件”对话框

除了上面提到的部件之外,媒体播放器还包孕一个视觉部件、一个节制面板部件。视觉部件顺序播放媒体文件包孕的各帧图像;节制面板部件容许用户停息、开始媒体文件的回放,或进行其他节制操作,例如查看媒体文件信息。

2.2 伪代码设计

前面我们懂得了构成媒体播放器GUI的各个部件,下面要开始“设想”一下这个法度榜样的详细构造。在正式编写代码之前,我们先用伪代码的形式写出这个法度榜样的运行历程,今后正式编写代码时只需把伪代码翻译成Java代码即可。下面给出了媒体播放器的伪代码描述:

利用的类名称:MediaPlayer

超类:Frame

监听 器分类:动作事故,节制器事故,菜单项事故,绘图事故,窗口事故

main:

* 为MediaPlayer工具分配内存。调用MediaPlayer构造函数,

创建主窗口(同时,隐含地创建/启动了AWT后台线程)

* 停止主法度榜样线程。此时AWT线程继承运行。

MediaPlayer构造函数:

* 设置主窗口的标题

* 注册窗口 监听 器,以处置惩罚窗口关闭事故

* 创建“文件”菜单

* 创建“打开”菜单项

* 把MediaPlayer工具注册成为“打开”菜单项动作事故的 监听 器

* 把“打开”菜单项加入“文件”菜单。

* 在“文件”菜单中加入一条水中分隔线

* 创建带反省框的“轮回”菜单项

* 把MediaPlayer工具注册成为“轮回”菜单项事故的 监听 器

* 把“轮回”菜单项加入“文件菜单”

* 在“文件”菜单中加入一条水中分隔线

* 按照创建“打开”菜单项的历程,创建“退出”菜单项

* 创建一个菜单条(MenuBar)

* 把“文件”菜单加入到菜单条

* 把新创建的菜单条设置为主窗口的菜单条

* 把主窗口的大年夜小设置为200*200像素

* 显示主窗口

* 停止构造函数

动作 监听 器:

当呈现动作时:

* 假如动作变糊弄源于“退出”菜单项,

* 触发一个给窗口 监听 器的窗口关闭事故

* 返回

* 创建一个“打开媒体文件”对话框

* 把对话框确当前目录设置为上次关闭时的目录

* 显示对话框。这个对话框是一个模式对话框

* 假如用户没有经由过程对话框选择媒体文件

* 返回

* 保存用户在对话框中选择的目录

* 假如曩昔已经创建JMF播放器工具

* 关闭该工具

* 根据指定的目录和名字,创建一个应用file:协议的媒体定位器(MediaLocator)工具,再使用该工具创建一个JMF播放器工具

* 假如呈现非常

* 显示差错信息,然后返回

* 把主窗口的标题设置为媒体文件的名字

* 把MediaPlayer工具注册为来自JMF播放器工具的节制器事故的 监听 器

* 让JMF播放器工具预先提取媒体内容

* 返回

节制器 监听 器:

当节制器被关闭:

* 假如JMF播放器的视觉部件存在,从MediaPlayer容器拆除视觉部件

* 假如JMF播放器的节制面板部件存在,从MediaPlayer容器拆除节制面板部件

* 返回

当媒体回放停止:

* 假如“轮回”菜单当选中

* 复位JMF播放器工具的开始光阴

* 让JMF播放器工具开始播放媒体

* 返回

当预提取媒体内容停止:

* JMF播放器工具开始播放媒体

* 返回

当实例化(realize)完成:

* 获取JMF播放器工具的视觉部件

* 假如视觉部件存在,则把它加入到MediaPlayer容器的

中心

* 获取JMF播放器工具的节制面板部件

* 假如节制面板部件存在,则把它加入到MedaPlayer容器的南方

* 履行pack()操作

* 返回

菜单项 监听 器:

当菜单项状态改变:

* 切换“轮回”菜单当选中的状态

* 返回

绘画事故 监听 器:

paint()措施:

* 假如尚未装入媒体文件

* 得到主窗口的宽度和高度

* 用蓝色添补窗口内的区域

* 创建一种字体(DialogInput/粗体),并将它设置为主

窗口的字体

* 谋略迎接信息的以像素计的宽度

* 把绘图颜色改成白色

* 在主窗口的中央显示出迎接信息

* 调用Frame超类的paint()措施,确保节制面板部件精确地画出

* 返回

update()措施:

* 调用paint()措施

* 返回

窗口 监听 器:

windowClosing:

* 调用dispose以履行windowClosed

* 返回

windowClosed:

* 假如已经创建JMF播放器工具

* 关闭JMF播放器工具

* 停止法度榜样

伪代码的前面三行声清楚明了媒体播放器的类名称、超类的名称和MediaPlayer类实现的 监听 器。带有main:前缀的行表示MediaPlayer的main()措施。类似地,带有“构造函数:”前缀的行属于MediaPlayer的构造函数。伪代码的另外内容分成五个 监听 器分区:动作 监听 器,节制器 监听 器,菜单项 监听 器,绘图 监听 器,窗口 监听 器。每一个分区分手包孕一个或多个措施。

三、编写代码

下面我们把前面的伪代码转换成Java代码:

import javax.media.*;

import java.awt.*;

import java.awt.event.*;

class MediaPlayer extends Frame implements ActionListener,

ControllerListener, ItemListener

{

Player player;

Component vc, cc;

boolean first = true, loop = false;

String currentDirectory;

MediaPlayer (String title)

{

super (title);

addWindowListener

(new WindowAdapter ()

{

public void windowClosing (WindowEvent e)

{

// 用户点击窗口系统菜单的关闭按钮

// 调用dispose以履行windowClosed

dispose ();

}

public void windowClosed (WindowEvent e)

{

if (player != null) player.close ();

System.exit (0);

}

});

Menu m = new Menu ("文件");

MenuItem mi = new MenuItem ("打开");

mi.addActionListener (this);

m.add (mi);

m.addSeparator ();

CheckboxMenuItem cbmi = new CheckboxMenuItem ("轮回", false);

cbmi.addItemListener (this);

m.add (cbmi);

m.addSeparator ();

mi = new MenuItem ("退出");

mi.addActionListener (this);

m.add (mi);

MenuBar mb = new MenuBar ();

mb.add (m);

setMenuBar (mb);

setSize (200, 200);

setVisible (true);

}

public void actionPerformed (ActionEvent e)

{

if (e.getActionCommand ().equals ("退出"))

{

// 调用dispose以便履行windowClosed

dispose ();

return;

}

FileDialog fd = new FileDialog (this, "打开媒体文件",

FileDialog.LOAD);

fd.setDirectory (currentDirectory);

fd.show ();

// 假如用户放弃选择文件,则返回

if (fd.getFile () == null) return;

currentDirectory = fd.getDirectory ();

if (player != null)

player.close ();

try

{

player = Manager.createPlayer (new MediaLocator ("file:" + fd.getDirectory () + fd.getFile ()));

}

catch (java.io.IOException e2)

{

System.out.println (e2);

return;

}

catch (NoPlayerException e2)

{

System.out.println ("不能找到播放器.");

return;

}

if (player == null)

{

System.out.println ("无法创建播放器.");

return;

}

first = false;

setTitle (fd.getFile ());

player.addControllerListener (this);

player.prefetch ();

}

public void controllerUpdate (ControllerEvent e)

{

// 调用player.close()时ControllerClosedEvent事故呈现。

// 假如存在视觉部件,则该部件应该拆除(为同等起见,

// 我们对节制面板部件也履行同样的操作)

if (e instanceof ControllerClosedEvent)

{

if (vc != null)

{

remove (vc);

vc = null;

}

if (cc != null)

{

remove (cc);

cc = null;

}

return;

}

if (e instanceof EndOfMediaEvent)

{

if (loop)

{

player.setMediaTime (new Time (0));

player.start ();

}

return;

}

if (e instanceof PrefetchCompleteEvent)

{

player.start ();

return;

}

if (e instanceof RealizeCompleteEvent)

{

vc = player.getVisualComponent ();

if (vc != null)

add (vc);

cc = player.getControlPanelComponent ();

if (cc != null)

add (cc, BorderLayout.SOUTH);

pack ();

}

}

public void itemStateChanged (ItemEvent e)

{

loop = !loop;

}

public void paint (Graphics g)

{

if (first)

{

int w = getSize ().width;

int h = getSize ().height;

g.setColor (Color.blue);

g.fillRect (0, 0, w, h);

Font f = new Font ("DialogInput", Font.BOLD, 16);

g.setFont (f);

FontMetrics fm = g.getFontMetrics ();

int swidth = fm.stringWidth ("奸淫 迎接 奸淫");

g.setColor (Color.white);

g.drawString ("奸淫 迎接 奸淫",

(w - swidth) / 2,

(h + getInsets ().top) / 2);

}

// 调用超类Frame的paint()措施,该paint()措施将调用Frame包孕的各个容器

// 和部件(包括节制面板部件)的paint()措施。

super.paint (g);

}

// 不履行背景清除操作,以免节制面板部件闪烁

public void update (Graphics g)

{

paint (g);

}

public static void main (String [] args)

{

new MediaPlayer ("媒体播放器1.0");

}

}

上述代码的详细含义这里就不再阐发。实际上,代码中的注释说清楚明了关键步骤的感化;别的,前面的伪代码也异常靠近这里的Java代码,可以看作对上述代码的具体解释。

四、编译和运行

假设前面的Java代码保存在MediaPlayer.java文件中,则编译敕令如下:

javac MediaPlayer.java

编译成功后,编译器天生两个.class文件:MediaPlayer.class,MediaPlayer$1.class。假如呈现编译差错,请反省以下各项:

源代码输入是否精确无误。

CLASSPATH设置是否精确。CLASSPATH该当包孕JMF的sound.jar、jmf.jar。

接下来就可以履行“java MediaPlayer”敕令启动媒体播放器。图一显示了媒体播放器刚启动之后的界面,图四是正在播放媒体的界面。

screen.width-333)this.width=screen.width-333;">

图四:用媒体播放器回放MPG片子

摘自:天极网   光阴:2003年9月11日

您可能还会对下面的文章感兴趣: