本文详细介绍用Java构造自己的媒体播放器
* 如果已经创建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”命令启动媒体播放器。图一显示了媒体播放器刚启动之后的界面,图四是正在播放媒体的界面。

图四:用媒体播放器回放MPG电影
责编:豆豆技术应用