#

組合方塊(combobox)是同時具備單行輸入方塊及清單方塊兩種特性的視窗元件,使用者可以在組合方塊裡直接輸入文字,或是由下拉清單中選取預設的項目。這一個章節介紹ttk組合方塊的使用方法。

30.1 建立組合方塊

如下是組合方塊的外觀,有一個文字輸入區,還有一個下拉清單方塊。使用者可以在文字輸入區輸入文字,也可以在下拉清單方塊中挑選預設提供的項目。

圖 30-1


ttk可以使用combobox命令建立組合方塊,如下是一個簡單的範例:



請看到第5行,-values後面必需緊接著一個清單式的資料,這個清單中的項目會被顯示在組合方塊的下拉清單方塊中。-textvariable的使用方法和ttk::entry一樣,它後面可以指定一個變數名稱,用來反映目前組合方塊輸入區的文字內容。

執行結果如下:

圖 30-2


使用者可以直接輸入想吃的水果,或是由下拉清單中挑選預設的項目。這些預設項目可以讓使用者少打一些字。

30.2 存取文字輸入區

文字輸入區的內容除了可以使用-textvariable指定的變數存取之外,也可以用下列的方法:



combobox的set命令可以用來設定文字輸入區的內容。上面的例子會把文字輸入區的內容設定為「西瓜」。而下方的程式,則會列印文字輸入區的內容。



30.3 使用範例

下面是一個常見的應用技巧,這個程式會在下拉清單中記住輸入區曾經使用過的內容。



這個程式把組合方塊綁定了Return事件,就是使用者按下鍵盤的Enter時,後方大括號裡的程式就會被執行。當事件觸發的時候,程式取出下拉清單中所有的項目,然後查看目前輸入區的內容,是否出現在這些項目中,如果沒有的話,就把目前輸入區的內容插入下拉清單的開頭,如此一來程式就會在下拉清單中自動記錄使用者曾經輸入的內容。

下面是另一個組合方塊的例子,它示範動態建立下拉清單項目的方法:



這個程式的重點在第3行的-postcommand選項,它就類似ttk::button的-command選項,指定給它的程式碼會在下拉清單顯示時被執行,也可以說是使用者在按下組合方塊右方的向下按鈕時就會執行。在這個例子裡,我把目前工作路徑下的檔案及目錄都掃進下拉清單,所以在不同的工作路徑下執行這個程式,下拉清單中的項目就會有不同的內容。

圖 30-3


上圖顯示了我的家目錄下所有的內容,因為我在家目錄下執行了這個程式。

30.4 常用選項

以下是其它常用的選項,有興趣的朋友請自己試看看吧!!

-height 指定組合方塊的高度
-justify 指定文字對齊的方式,它的值可以是left、right或center。
-width 指定組合方塊的寬度。

圓鈕方塊也提供了cget及configure等標準的視窗元件命令,它們的用法請參考這一章的說明。

17 個意見

米粒 | 2009年12月18日 清晨7:06

簡單易懂
程式碼有項目數字耶~~~
下次再好好問你怎用出來的

dai | 2009年12月18日 上午11:17

其實在網誌的原始文件裡,並沒有為程式碼加入行號。那些行號是我用javascript幫它們自動加上的~也就是說行號是網誌載入時,程式動態產生的。哈~~我太懶了。

翊翾 | 2010年1月12日 下午5:04

Dai你好^^~
因為postcommand是拉下選單馬上被執行
如果我想拉下清單點選裡面的變數之後
再執行另外一個副程式,不知道有無這指令?
還是就只有postcommand可以使用了...?
請Dai给個寶貴的意見^^~

dai | 2010年1月12日 下午6:00

請試試下面的範例:

ttk::combobox .cmb -values "1 2 3"
bind .cmb <> {puts [.cmb get]}
pack .cmb

翊翾 ~~ 你真是有禮冒的好孩子 @@

翊翾 | 2010年1月12日 下午6:33

那個.....我有個疑問
bind 中不用給條件嗎?

^^被Dai稱讚了耶~

dai | 2010年1月12日 晚上7:11

抱歉!! 忘記把角號換成html的語法,所以角號裡的內容顯示不出來

ttk::combobox .cmb -values "1 2 3"
bind .cmb <ComboboxSelected> {puts [.cmb get]}
pack .cmb

這個當然是要大大的稱讚一番~~如果人人都像你一樣的有禮貌,世界一定會更美好~呵呵 值得效法 ~ 值得效法 ~

翊翾 | 2010年1月13日 上午9:39

^^Dai我試出來囉
正是我要的功能呢~
不過用法可能要稍微改變一下
bind .cmb <> {puts [.cmb get]}
中間的<>要多打一次,不然好像會一直說找不到這指令的說

感謝建議啦~又吸收了一點點功力啦(笑)

dai | 2010年1月13日 上午10:47

沒錯 ~~ 是要打兩次,我的html還是打錯了 哈哈。

匿名 | 2010年10月7日 下午4:06

我用了上面的(蘋果,西瓜,蕃茄)範例來練習一下,但是我有一個問題想請教一下,那就是當我在輸入文字區輸入中文後,它就會錯誤訊息"alloc invalid block...",但是如果輸入英文的話就沒有問題出現,我想請問一下為什麼會這樣的呢?

匿名 | 2010年10月8日 上午9:56

我的問題(打中文會有錯誤訊息)已經解決了。如果用8.5版本的話,就會有這個問題存在,我想可能是8.5版本的bug,後來我安裝8.6版本的話,問題就不會發生了。

匿名 | 2011年2月23日 下午3:58

30.3的第一個範例程式中
bind .cmb 應該改為bind .cmb
R要大寫

dai | 2011年2月27日 上午11:11

Hi 匿名的朋友,

已經修正了,謝謝哦!!

匿名 | 2013年12月11日 下午2:18

Hello dai,

我想將翊翾的例子,選了值之後存入變數,到combobox外再運算該怎麼做?

匿名 | 2013年12月12日 晚上7:11

像這樣

:ttk::combobox .cmb -values "1 2 3" -textvariable ::cmbVal
pack .cmb

從此以後你可以在程式的任何位置用 $::cmbVal 來取得combobox選中的值

Mike | 2014年12月23日 下午5:36

不好意思,又來麻煩Dai大大,我這邊又遇到一個問題,想請問一下要如何把舊的 label 給 unset 掉?(不知道可不可以這樣說?)
一個很簡單combobox選擇後顯示的程式,但只要重複選之後,就會說舊得已經存在。
proc test {op1} {
label .text -text $op1
place .text -x 0 -y 30
}

set list "A B C"
set var A
test A
::ttk::combobox .combo -values $list -textvariable var -state readonly
place .combo -x 0 -y 0
bind .combo <> {test [.combo get]}

似乎可以用configure可以來改設定,但若是今天有元件很多怎麼辦?也是要一個一個改嗎?
可不可再proc開頭就把所有設定給unset掉,然後讓我重新再來一次就好?
這好像是一個蠻笨的問題。

匿名 | 2014年12月24日 下午2:18

Hi Hu Mike,

我想你可以開一個LIST儲存已選擇的ELEMENT

匿名 | 2014年12月24日 下午2:48

tk widget 可以 destroy 例如

if {[winfo exists .text]} {destroy .text}

留下您的意見

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