首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java Media Framework (JMF) 打造跨平台媒體播放器:從 GUI 設計到核心播放邏輯

     編輯:Java 程式設計入門

專案目標

使用 JMF (Java Media Framework) 建立具備「開啟媒體檔案」、「循環播放切換」、「退出」功能的 AWT/Swing 媒體播放器,支援音訊/視訊多種格式,跨 Windows/Linux/Solaris 運行。

架構設計

層級組件技術選型
UI 層主視窗、選單列、檔案選擇器、視覺元件、控制面板AWT `Frame`/`MenuBar`/`FileDialog` + JMF `Player` 視覺/控制元件
媒體層媒體定位、解碼、渲染、控制JMF `Manager`、`Player`、`Controller`、`DataSource`
事件層使用者操作、播放狀態變化AWT 事件監聽器 + JMF `ControllerListener`

核心代碼骨架

import java.awt.*;
import java.awt.event.*;
import javax.media.*;
import javax.media.controller.*;

public class MediaPlayer extends Frame implements ActionListener, ControllerListener {
    private Player player;
    private Component visualComp, controlComp;
    private boolean looping = false;

    public MediaPlayer() {
        setTitle("媒體播放器 1.0");
        setLayout(new BorderLayout());
        setBackground(Color.LIGHT_GRAY);

        // 選單列
        MenuBar mb = new MenuBar();
        Menu fileMenu = new Menu("檔案");
        MenuItem openItem = new MenuItem("開啟");
        CheckboxMenuItem loopItem = new CheckboxMenuItem("循環播放");
        MenuItem exitItem = new MenuItem("退出");
        openItem.addActionListener(this);
        loopItem.addActionListener(this);
        exitItem.addActionListener(this);
        fileMenu.add(openItem);
        fileMenu.addSeparator();
        fileMenu.add(loopItem);
        fileMenu.addSeparator();
        fileMenu.add(exitItem);
        mb.add(fileMenu);
        setMenuBar(mb);

        // 視窗關閉處理
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) { shutdown(); }
        });

        pack();
        setSize(640, 480);
        centerOnScreen();
        setVisible(true);
    }

    private void centerOnScreen() {
        Dimension scr = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension frm = getSize();
        setLocation((scr.width - frm.width)/2, (scr.height - frm.height)/2);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String cmd = e.getActionCommand();
        if ("開啟".equals(cmd)) openFile();
        else if ("循環播放".equals(cmd)) looping = ((CheckboxMenuItem)e.getSource()).getState();
        else if ("退出".equals(cmd)) shutdown();
    }

    private void openFile() {
        FileDialog fd = new FileDialog(this, "選擇媒體檔案", FileDialog.LOAD);
        fd.setVisible(true);
        String dir = fd.getDirectory();
        String file = fd.getFile();
        if (dir == null || file == null) return;

        try {
            if (player != null) player.close();
            MediaLocator ml = new MediaLocator("file:" + dir + file);
            player = Manager.createRealizedPlayer(ml);
            player.addControllerListener(this);

            // 視覺元件
            if (visualComp != null) remove(visualComp);
            visualComp = player.getVisualComponent();
            if (visualComp != null) add(visualComp, BorderLayout.CENTER);

            // 控制面板
            if (controlComp != null) remove(controlComp);
            controlComp = player.getControlPanelComponent();
            if (controlComp != null) add(controlComp, BorderLayout.SOUTH);

            validate();
            player.start();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void controllerUpdate(ControllerEvent e) {
        if (e instanceof EndOfMediaEvent && looping) {
            player.setMediaTime(new Time(0));
            player.start();
        }
    }

    private void shutdown() {
        if (player != null) { player.close(); player = null; }
        dispose();
        System.exit(0);
    }

    public static void main(String[] args) {
        new MediaPlayer();
    }
}

JMF 關鍵類別速查

類別角色
`Manager`工廠:`createPlayer(DataSource)`、`createRealizedPlayer(MediaLocator)`
`Player`控制介面:`start()`/`stop()`/`setMediaTime()`/`getVisualComponent()`/`getControlPanelComponent()`
`ControllerListener`事件回調:`RealizeCompleteEvent`、`PrefetchCompleteEvent`、`EndOfMediaEvent`、`ControllerErrorEvent`
`MediaLocator`統一資源定位:`file:`、`http:`、`rtp:`、`javasound:`
`Format`媒體格式描述:`VideoFormat`、`AudioFormat`

支援格式與編碼器

  • JMF 2.1.1e 內建:GSM、MP3 (需授權)、H.261/H.263、MPEG-1、AVI、QuickTime、WAV、AIFF、AU。
  • 擴展:安裝 JMF Registry 註冊第三方編解碼器 (如 FFmpeg JNI 橋接)。
  • 查詢支援格式:`PackageManager.getPackageManager().getSupportedFormats()`。

已知限制與現代化替代

限制現代替代方案
JMF 2003 年後停更,無 H.264/HEVC/VP9 支援VLCJ (Java binding for libvlc) — 全格式、硬解、跨平台
Applet 部署模式已死JavaFX `MediaPlayer` + `MediaView` (內建 H.264/AAC,模組化部署)
AWT/Swing 視覺元件重繪問題JavaFX 場景圖自動合成、GPU 加速
無模組化支援 (JPMS)VLCJ / JavaFX 均為模組化庫

遷移建議

  1. 新專案直接採用 **JavaFX Media** (JDK 8+ 隨附、JDK 11+ 需獨立引入 `javafx-media` 模組)。
  2. 需播放專有格式/串流協定 (RTSP/RTMP/HLS) → **VLCJ 4.x** + `vlc` 系統安裝。
  3. 舊 JMF 專案維護:保留 JMF 2.1.1e JAR,配合 `jmf.jar`、`sound.jar`、`mediaplayer.jar` 置於模組路徑。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved