#

這篇文章將介紹Tk內建的各種對話視窗,分別是,顯示文字資訊給使用者看的訊息視窗,提供使用者選擇顏色的對話視窗,及提供使用者選取目錄、開啟檔案及儲存檔案的對話視窗等。

37.1 訊息對話視窗 (tk_messageBox)

訊息對話視窗是一種顯示文字訊息的視窗元件,一般的情況下程式的設計者使用訊息視窗,傳達某些訊息讓使用者知道,並且取得使用者的回應,然後再決定程式該如何執行。在Tk裡使用tk_messageBox即可叫出訊息對話視窗,語法如下:

tk_messageBox ?option value?
下方是一個簡單的使用例子:

程式37-1

tk_messageBox \
   -title "訊息" \
   -message "這就是最簡單的對話方塊" \
   -icon info

這個例子使用-title選項指定對話視窗的標題,使用-message指定顯示給使用者看的文字訊息,-icon 則用來指定訊息視窗上要顯示的小圖示。執行的結果如下圖:

圖 37-1

除了info之外-icon可以接受的值如下:
  • error : 顯示「錯誤」的圖示。
  • info : 顯示「資訊」的圖示。
  • question : 顯示「問號」的圖示。
  • warning : 顯示「警告」的圖示。
接下來要示範tk_messageBox的-type選項,這個選項可以讓程式的設計者,提供更多種類的對話視窗來和使用者互動,例如:

程式37-2

set ret [tk_messageBox \
   -title "注意" \
   -message "是否不儲存檔案就離開?" \
   -icon warning \
   -default cancel \
   -type yesnocancel]

puts $ret

在這個例子裡我用-type指定對話視窗顯示「是(yes)」、「否(no)」及「取消(cancel)」等3個按鈕,像這樣的對話視窗常被使用在某個程式關閉時,要求使用者存檔之類的事情。另外程式中的-default選項可以用來指定預設的按鈕,預設的按鈕會在使用者按下Enter時被執行。這個程式執行起來像這樣:

圖 37-2

由於我們在程式裡將-default指定為cancel,所以圖中的「取消」按鈕就被當成了預設項目。其它值得注意的地方是,tk_messageBox在使用者按下按鈕時,會回傳使用者選中的按鈕,也就是說在上面的例子裡,ret的值可能會是yes、no或是cancel其中之一,可想而知的設計程式的人,可以用ret的值決定接下來要執行的動作。

讓我們再看一個訊息對話視窗的例子:

程式37-3

set ret [tk_messageBox \
   -title "錯誤" \
   -message "無法開啟檔案 test.tcl' ?" \
   -icon warning \
   -default retry \
   -type abortretryignore ]

puts $ret

這個例子顯示了「中止(abort)」、「重試(retry)」及「略過(ignore)」等三個按鈕。

圖 37-3

由於程式中-default被指定為retry,所以理所當然的它被變成了預設按鈕。注意哦!! 如果-default指定了一個不屬於-type選項值出現的按鈕,程式將會出錯。例如,-type指定為yesnocancel,如果把-default指定為retry,這樣就是不正確的。

以下是-type可以接受的值:
  • abortretryignore : 顯示「中止」、「重試」及「略過」等三個按鈕。
  • ok : 顯示「確定」按鈕。
  • okcancel : 顯示「確定」及「取消」按鈕。
  • retrycancel : 顯示「重試」及「取消」按鈕。
  • yesno : 顯示「是」及「否」按鈕。
  • yesnocancel : 顯示「是」、「否」及「取消」等3個按鈕。

37.2 顏色選擇對話視窗 (tk_chooseColor)

提供使用者選擇顏色的對話視窗,它的使用方法很簡單也很固定,大部分的情況都這樣用:

程式37-4

set color [tk_chooseColor \
   -initialcolor "#FF0000" \
   -title "選擇顏色"]

if {$color == ""} {
   puts "沒有選擇顏色"
} else {
   puts "選擇了 : $color"
}

如同tk_messageBox一樣-title用來設定視窗的標題,而-initialcolor則用來指定對話視窗跳出來時,預設選中的顏色。tk_chooseColor執行的回傳值是RGB的色碼,如果使用者沒有選擇任何顏色的話回傳值是空字串。它執行起來的畫面如下:

圖 37-4

37.3 目錄選擇對話視窗 (tk_chooseDirectory)

提供使用者選擇目錄的對話視窗,它的使用方法一樣很簡單也很固定,大部分的情況都這樣用:

程式37-5

set dir [tk_chooseDirectory \
   -initialdir ~ \
   -title "Choose a directory"]

if {$dir == ""} {
   puts "沒有選擇目錄"
} else {
   puts  "選擇了: $dir"
}

程式裡-title一樣是用來設定視窗的標題的,而-initialdir則用來指定對話視窗跳出來時,預設選中的目錄,或是說成起始的選擇目錄也行,如果使用者選了某個目錄然後按確定,回傳值會是使用者選中的目錄,否則回傳空字串。

程式的執行畫面如下:

圖 37-5

37.4 檔案開啟對話視窗 (tk_getOpenFile)

檔案開啟對話視窗讓使用者由檔案系統中選取檔案,並回傳選中檔案的路徑。使用的範例如下:

程式37-6

set types {
   {{Text Files}       {.txt}        }
   {{TCL Scripts}      {.tcl}        }
   {{C Source Files}   {.c}          }
   {{All Files}        *             }
}
set filename [tk_getOpenFile \
   -filetypes $types \
   -initialdir ~ \
   -initialfile "a.txt" ]

if {$filename != ""} {
   # 開啟你選中的檔案
}

程式中-initialdir用來指定選取檔案的啟始目錄,-initialfile是預設要選取的檔案名稱,而-filetypes選項則可以用來設定對話視窗的「檔案類型」欄位。請看下圖的下拉式組合方塊,然後再比對程式範例中types變數的結構就知道是怎麼使用了。

圖 37-6

§ 關於檔案開啟對話視窗

請特別注意哦!! 檔案開啟對話視窗的結果是「檔案的路徑」而不是「檔案的通道代碼」,也就是說如果你想要讀出使用者挑中的檔案內容,還是要用open、read或gets...等,標準的檔案讀取方法。讀取檔案的方法請參見「11. Tcl - 檔案I/O」。

37.4 檔案儲存對話視窗 (tk_getSaveFile)

檔案儲存對話視窗讓使用者選擇檔案系統中的檔案,並回傳檔案的路徑,基本上它的功能和檔案開啟對話視窗是一樣的,只有一些小差異,一是視窗標題上顯示的文字是不一樣的,另外,由於這個對話視窗是用來儲存檔案用的,所以接受使用者輸入一個不存在的檔案名稱。使用範例如下:

程式37-7

set types {
   {{Text Files}       {.txt}        }
   {{TCL Scripts}      {.tcl}        }
   {{C Source Files}   {.c}          }
   {All Files}        *             }
}
set filename [tk_getSaveFile \
   -filetypes $types \
   -initialdir ~ \
   -initialfile "a.txt" ]

if {$filename != ""} {
   # 開啟你選中的檔案
}

tk_getSaveFile和tk_getOpenFile的選項是一樣的,就不再多說了。執行的畫面如下:

圖 37-7

§ 關於檔案儲存對話視窗

注意哦!! 檔案儲存對話視窗的結果是「檔案的路徑」而不是「檔案的通道代碼」,所以你還是要自己利用標準的寫入檔案方法,才可以把你想要的資訊存入使用者挑中的檔案,寫入檔案的方法請參見「11. Tcl - 檔案I/O」。

最後!! 不知道大家有沒有發現上面提到的對話視窗,都不像其它widget一樣需要指定path? 沒錯它們都不需要指定path,但它們都有一個-parent選項,你可以把某個視窗元件的path指定給這個-parent選項,這樣將會使你的對話視窗變成局部的頂層視窗,而不是全面性的頂層視窗。另外一個值得注意的地方是!! 這些對話視窗在不同的平台會有不一樣的效果,也就是它的外觀及功能會因為作業系統而不同。

8 個意見

isPeter | 2011年1月10日 下午5:34

hello Dai,

終於等到你的最後一篇文章,這一系列的教學文章,對於初學 TK/TCL 而言,很實用。國內關於 TK/TCL 實在是很少,而此系列文章寫的很好,易懂易吸收,對於初學者來說,真的是幫助非常大。

私心建議,集結出書,我要預購一本。

無以回報,只能將我看到的各個小錯誤回報,省去將來你若要出書,校稿的時間。

---

照慣例,再提出一個小錯誤:

"圖 37-1" 跟程式碼上面的 "-message "Tcl/Tk的對話方塊" 字不一樣。

dai | 2011年1月16日 上午9:42

hi isPeter,

才要謝謝你熱心幫忙找錯誤哩!! 這一篤文章真的是拖了很久~哈哈!!
本站的內容要到出書等級,自覺還有一段距離,主要是內容不夠豊富、文章不夠流暢。也許各篇文章還要再不斷的修正幾次吧!! 不管怎麼說,很謝謝你的支援。有大家的支持才讓我有繼續寫下去的動力。

匿名 | 2012年3月20日 上午10:00

Dai大,

我是剛剛入門tcl/tk的新手,看了你的網站後覺得很讚,讓大家覺得tcl/tk是非常親民的語言..:)
有個問題想請教一下,如果我有很多視窗,且希望視窗產生都像是dialog一樣,parent視窗是disable,必須等到子視窗返回後,才enable,要如何做呢?

Thanks.

Felix

dai | 2012年3月20日 中午12:32

嗯 ~ 以下是我自己慣用的dialog套件 ~ 請試試看合不合你用!!

http://dl.dropbox.com/u/7833932/tw.zip

裡面有一個dialog.tcl,有興趣的話可以打開來看看,可能有你需要的程式碼範例!!

另外,解壓縮後請找到 test/test-dialog.tcl 用wish執行它,它會顯示 message box , font box , input box 等3個範例!!

希望對你有幫助 ^^

匿名 | 2012年3月20日 下午3:02

Dai大,

謝謝,我run不起來test-dialog.tcl也。。。error是
invalid command name "::oo::class" while executing ....

不知哪裡忽略了,還在check當中。

Felix

dai | 2012年3月20日 晚上8:18

嗯 ~ oo 是Tcl 8.6 + 才支援的物件導向命令!!. 猜是你的Tcl版本不對

匿名 | 2012年3月21日 上午10:26

Dai大,

我用的是Tcl 8.5.1...:)
我看了一下您提供的dialog.tcl, 裡面有一個grab指令+tkwait可以滿足我的需求,
非常感恩!!

Felix

Emil | 2012年7月18日 下午3:51

Dai大您好,
我是最近才開始接觸TCL,能夠search到您的部落格真是幫助非常的大,
看您此系統3/20的留言有個dialog sample可以參考,
但是連結好像已經失效,不知是否還有機會能取得此sample參考學習,
thanks.

留下您的意見

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