#

經過前面21章的洗禮相信大家都對Tcl/Tk已經有基礎的認識了。接下來的幾個章節將會進入實戰的領域,也就是說我們會寫一些比較像樣的程式,讓你可以用自己寫的程式處理一些日常工作。好了!! 我們的第一個程式實作是「MP3播放器」,由這個程式切入希望會讓你覺得有趣些。

22.1 功能規劃

在開始寫程式之前,讓我們先來做一些簡單的功能規劃,想想看一個堪用的MP3播放器應該有哪些功能?

  • 播放控制:播放、暫停、停止、搜尋、上一首、下一首
  • 播放資訊:時間、曲名
  • 循環播放:單首、全部
  • 音量控制:增大、減小
  • 播放清單:加入、移除

嗯~~差不多,以一個自用的程式來說,功能上應該暫時夠了。目標就先暫訂這樣好了!! 更多的功能等到有需要時再來寫。 為了方便說明,我們就叫這個播放器iPlayer吧。

確定了功能之後,下一步我們要設計操作介面,下面是一張草稿,我打算讓完成後的程式長成類似這樣,這是大概的規劃,最後的成品還是得以實作的過程來決定。


圖 22-1 操作介面設計

在這張圖中,最上面05:30的位置用來顯示剩餘的播放時間,然後小荳芽之後的文字是目前正在播放的檔案。接下來是一些控制播放還有音量的按鈕,下面最大的方塊是顯示播放清單的位置。最底部的方塊則是播放進度的捲軸及循環控制的按鈕。

22.2 安裝snack套件

在之前的文章裡曾經提到snack是一個外部的套件,它專門用來播放音樂檔、控制音量及錄音。在這裡我打算使用它當作iPlayer的核心,所以請大家先把snack套件裝起來。如果之前你己經安裝過的話可以跳過這個章節。

□ 檢查snack安裝

首先請大家確定snack是否已經裝在系統裡面了,如果已經裝過的話,就不用在安裝。請執行下面的一行程式,它可以幫你列印出snack套件的版本。



如果說你的系統裡已經有安裝snack,這行程式的輸出應該會是「2.x」也就是snack的版本。如果執行這個程式發生錯誤,就表示你還沒有裝snack套件。若是這種情況的話,請依照下面的圖安裝。注意哦!! 你必需安裝ActiveTcl下面的指令才會成功。

Windows下安裝:

圖 22-2 Windows下安裝snack


Linux及Mac下安裝:

圖 22-3 Linux及Mac下安裝snack


執行完安裝步驟後,請再次用上面的程式確定snack有安裝成功。

22.3 跑起來再說

別管太多,讓我們先把程式跑起來。請自行建立一個iPlayer.tcl的程式檔,然後比照開發大型專案的規矩,幫iPlayer建立一個同名的名稱空間,以後所有的程式都要塞在這個名稱空間裡面。



下一步我們要寫一些測試程式,確定snack是可以運作的。注意!! 寫完下面的程式先不要執行它!! 因為還有一些小地方要修改。



上面的程式規劃了兩個名稱空間變數,分別是snd及currentFile。其中snd用來儲存播放物件,而currentFile用來儲存正在播放的檔案路徑,由於它們都是整個程式會用到的資訊,所以要用名稱空間變數儲存它們。

init程序先後載入了snack套件還有建立播放物件。注意哦!! 新建立的播放物件被儲存在snd裡頭,往後整個程式裡都可以使用它。

在play程序中,我們先假設init程序已經執行過了,而且播放物件已經載入MP3檔案。在這樣的情況下用播放物件的play命令就可以播出聲音。

最後請注意到程式裡的這一行:



這是為了方便測試用的,因為init程序裡只有建立播放物件,並沒有指定要載入哪一個檔案,所以現在它的功能是確保執行::iPlayer::play程序之前有載入MP3的檔案。注意哦!! 你要真的在c:磁碟下放一個01.mp3檔案,否則的話這個測試程式會跑不起來。

都沒問題後,請大家用wish去執行這個程式。記得開喇叭,播放程式已經啟動了。

22.4 建立圖形介面

現在讓我們修改一下剛剛的程式,把建立圖形介面的程序加進去。請在::iPlayer的名稱空新裡加入一個專門用來建立圖形介面的程序,程序中用到的小圖示你可以在這篇文章的最後面下載。



這個程序總共建立了播放、暫停及停止等3個按鈕,並且分別指定它們的-command選項為::iPlayer::play、::iPlayer::pause及::iPlayer::stop。其中只有play是已經寫好的程序,而pause及stop則還沒實作,這不要緊就先暫時這樣子!! 它們的程式碼晚一點再來處理。

這個程序寫好了之後,我們還需要在適當的時機執行它,我認為在init程序裡執行是個不錯的選擇,所以改一下init程序在最後一行加入gui_init來執行它。

☆ 先初始化整個程式共用的資料,然後才建立圖形介面,這是一個好的方法。



ok!! 現在我們可以再測試一次程式看看效果如何,它執行起來應該像這樣:

圖 22-4


嗯,外觀還ok,但為什麼還沒按play音樂就自動播起來了,怎麼會這樣呢? 還記得我們在程式的最後一行有執行::iPlayer::play對吧!! 就是它搞得鬼,連同註解一起刪除掉,然後再執行一次。



這樣正常多了,音樂會在按下play時才會開始播放。

都已經走到這一步了,就繼續把pause及stop的程序加進去吧!!



這兩個程序出乎意料的簡單,現在3個按鈕都可以正常運作了,不會很困難吧!!

22.5 重點回顧

目前我們已經寫出程式大概的架構了,雖然現在還有很多問題要處理,不過別擔心會慢慢完成的。現在你只要先熟悉播放MP3的步驟就可以了。

  1. 用「::snack::sound」建立播放物件(假設是snd)
  2. 用「$snd configure -file filepath」 載入要播放的檔案
  3. 用「$snd play」來播放檔案
  4. 用「$snd pause」暫停播放
  5. 用「$snd stop」停止播放

22.6 程式資源

如果你打的程式跑不出來的話,可以這在邊下載我打的程式iPlayer.tcl

另外下面是這個程式會用到的圖片,請自己另存新檔。 注意哦!! 這些圖片要和iPlayer.tcl放在同一個資料夾裡面。

7 個意見

Unknown | 2014年2月28日 上午10:11

Hi dai,
感谢您的教程。
本节最后面停止播放的button应该是用 $snd stop吧?似乎有笔误哦。

匿名 | 2014年3月10日 上午11:35

已經修正了,謝謝 ~

Mike | 2014年12月30日 上午10:48

可否請問一下,tcl/tk 是否可以讓一個button有兩個功能呢?
我想把start/stop play改成一個button,是否有實作的方法?
我想到的方式,最後會陷入無限迴圈
ttk::button .btn1 -text "Start" -command {
set ::start_stop 1
.profor.btn1 configure -text "Stop" -command { set ::start_stop 0 }
[play function]
.profor.btn1 configure -text "Start" -command { ...loop... }

另外ttk::button才可以在裡面改變字體,button卻不行,這是正常的嗎?

匿名 | 2014年12月30日 上午11:36

可以配合 if...else...像這樣:

set ::var "start"

set btn [ttk::button .btn -textvariable ::var -command {
if {$::var == "start"} {
puts "啟動程序..."
set ::var "stop"
} else {
puts "停止程序..."
set ::var "start"
}
}]

pack .btn -expand 1 -fill both

-----------------
button 可以指定 -font 選項,參考手冊:

http://www.tcl.tk/man/tcl8.6/TkCmd/options.htm#M-font

Mike | 2014年12月31日 上午11:07

Sorry~Dai 大大,我把 ttk::button 和 button 寫反了,
我在button下可以用 -fg 和 -bg 來改變字體和背景的顏色,但換到ttk::button之後就找不到了。

嗯~用 if...else 有點麻煩,因為我開始後的程序是不會跳出來的,我目前還是用兩個button,但是把位置疊在一起看起來像是一個,應該算是作弊吧?我的狀況是這樣:
set start_stop 1
button .btn1 -text "Start" -command { while {start_stop} {...} }
button .btn2 -text "Stop" -command { set start_stop 0 }

匿名 | 2015年1月6日 上午9:07

ttk::button 需要使用 -style 指定一個新的style 並用 ttk::style configure 來設定前景、背景及字型。

若-command執行的是一個用變數控制的迴圈,建議修改程式執行的邏輯或是用thread來處理。

Unknown | 2016年8月25日 下午4:58

請問,我在安裝SNACK,為何會出現下列錯誤? 謝謝!

c:\Tcl\bin>teacup install snack
Resolving snack ... Not found in the archives.

While a more fuzzy search disregarding letter case and accepting
substrings was done, we are sorry to say that it yielded no possible
candidates for installation either.

Questions to consider:
Have you spelled the name correctly ?
Including the proper case of characters ?

Note that teacup's 'search' command allows you to locate packages by
subject, categories, and the like.


Aborting installation, was not able to locate the requested
entity.

留下您的意見

Theme Design by devolux.org. Converted by Wordpress To Blogger for WP Blogger Themes. Sponsored by iBlogtoBlog
This template is brought to you by : allblogtools.com | Blogger Templates