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

使用 JMF 打造跨平台 Java 媒體播放器:從設計到實作完整指南

     編輯:Java 相關知識

專案目標與架構概覽

本文將引導您從零建立一個基於 Java Media Framework (JMF) 的媒體播放器,具備以下功能:

  • AWT 視窗應用程式,選單驅動操作
  • 「檔案」選單:開啟媒體、循環播放切換、結束程式
  • 跨平台執行 (Windows/Linux/macOS)
  • 支援 JMF 相容的多種音訊/視訊格式 (MPEG、AVI、WAV、AU 等)
  • 視覺化播放畫面與控制面板 (播放/暫停/音量/進度條)

GUI 設計規劃

主視窗:標題「媒體播放器 1.0」,200x200 像素,藍色背景顯示歡迎訊息
選單列:檔案選單含三項 (開啟/循環/結束),循環項目為 CheckboxMenuItem
檔案對話框:模態對話框,記憶上次開啟目錄
播放元件:JMF Player 提供的 Visual Component (影像區) 與 Control Panel Component (控制列)

偽代碼邏輯流程

核心類別 MediaPlayer extends Frame 實作三大監聽器:

  • ActionListener:處理選單項目事件 (開啟檔案、結束程式)
  • ControllerListener:監聽 JMF Player 狀態 (Realized、Prefetched、EndOfMedia、Closed)
  • ItemListener:處理循環播放核取方塊狀態變更
  • WindowListener:視窗關閉時釋放 Player 資源並結束程式
  • 繪圖邏輯:paint() 繪製歡迎畫面,update() 防止閃爍

核心程式碼實作 (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(); }
            public void windowClosed(WindowEvent e) {
                if (player != null) player.close();
                System.exit(0);
            }
        });
        // 建立選單
        Menu m = new Menu("檔案");
        MenuItem open = new MenuItem("開啟"); open.addActionListener(this); m.add(open);
        m.addSeparator();
        CheckboxMenuItem loopItem = new CheckboxMenuItem("循環", false);
        loopItem.addItemListener(this); m.add(loopItem);
        m.addSeparator();
        MenuItem exit = new MenuItem("結束"); exit.addActionListener(this); m.add(exit);
        setMenuBar(new MenuBar()); getMenuBar().add(m);
        setSize(200, 200); setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("結束")) { 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 (Exception ex) { System.out.println(ex); return; }
        if (player == null) return;
        first = false;
        setTitle(fd.getFile());
        player.addControllerListener(this);
        player.prefetch();
    }

    public void controllerUpdate(ControllerEvent e) {
        if (e instanceof ControllerClosedEvent) {
            if (vc != null) { remove(vc); vc = null; }
            if (cc != null) { remove(cc); cc = null; }
        } else if (e instanceof EndOfMediaEvent) {
            if (loop) { player.setMediaTime(new Time(0)); player.start(); }
        } else if (e instanceof PrefetchCompleteEvent) {
            player.start();
        } else 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, 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 sw = fm.stringWidth("*** 歡迎 ***");
            g.setColor(Color.white);
            g.drawString("*** 歡迎 ***", (w - sw) / 2, (h + getInsets().top) / 2);
        }
        super.paint(g);  // 確保控制面板正確繪製
    }
    public void update(Graphics g) { paint(g); }  // 避免背景清除造成控制面板閃爍

    public static void main(String[] args) { new MediaPlayer("媒體播放器 1.0"); }
}

編譯與執行步驟

  1. 確認 CLASSPATH 包含 JMF 函式庫:sound.jar、jmf.jar
  2. 編譯:javac MediaPlayer.java (產生 MediaPlayer.class、MediaPlayer$1.class)
  3. 執行:java MediaPlayer

關鍵技術重點總結

技術點說明
JMF Player 生命週期Realizing → Prefetching → Started,各階段透過 ControllerEvent 通知
視覺/控制元件整合RealizeComplete 後取得元件並加入 Container,呼叫 pack() 調整視窗大小
循環播放實作EndOfMediaEvent 中重設 mediaTime 為 0 並再次 start()
資源釋放ControllerClosedEvent 移除元件;windowClosed 呼叫 player.close()
繪圖最佳化update() 直接呼叫 paint() 避免清除背景導致控制面板閃爍

擴充建議

  • 加入播放清單管理 (List/Vector 維護多個 MediaLocator)
  • 支援網路串流播放 (https://, rtp:// 協定)
  • 加入影音擷取/轉檔功能 (JMF Processor API)
  • 移植至 Swing (JFrame) 獲得更現代化外觀
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved