Posted on 2008-08-13 22:26
zht 閱讀(1528)
評(píng)論(1) 編輯 收藏 所屬分類:
Swing
首先swing是單線程的,這個(gè)是這篇文章的前提,也是意義所在,當(dāng)swing界面程序啟動(dòng)的時(shí)候,會(huì)啟動(dòng)3個(gè)進(jìn)程,
1、主線程
2、系統(tǒng)工具包線程:負(fù)責(zé)捕獲操作系統(tǒng)事件,然后將事件轉(zhuǎn)換成swing的事件,然后發(fā)送到事件派發(fā)線程EDT
3、事件派發(fā)線程(EDT):將事件派發(fā)到各個(gè)組件,并負(fù)責(zé)調(diào)用繪制方法更新界面
所有的事件,例如鍵盤,鼠標(biāo)事件,都會(huì)由工具包線程轉(zhuǎn)換成swing事件,然后放到事件隊(duì)列EventQueue中,而這個(gè)EventQueue的派發(fā)機(jī)制是由EDT來(lái)管理的。

所以任何修改組件狀態(tài)的方法都應(yīng)該在EDT中執(zhí)行,包括構(gòu)造方法。Swing這樣的構(gòu)造原理經(jīng)常會(huì)造成的情況就是,在EDT中執(zhí)行長(zhǎng)時(shí)間的事件,使EDT不能及時(shí)響應(yīng)更新界面的事件,就是所說(shuō)的界面卡住,這種不光是新手就是比較熟練的程序員也會(huì)犯的一個(gè)錯(cuò)誤。所以必須避免在EDT中執(zhí)行長(zhǎng)時(shí)間的操作,而避免的方法就是多線程,啟動(dòng)另外的線程來(lái)處理冗長(zhǎng)的操作,比如操作數(shù)據(jù)庫(kù),讀寫文件等,在這過(guò)程中可能要更新界面來(lái)給用戶以提示,比如顯示一個(gè)進(jìn)度條,過(guò)一段事件更新一下界面,但是在EDT以外的線程中更新界面都是無(wú)效的,這在前面已經(jīng)說(shuō)過(guò),要更新界面就要將對(duì)界面的更新操作放到EDT中,但是事件又是在另外的線程中執(zhí)行的,要解決這個(gè)問(wèn)題就要使用SwingUtilities提供的一個(gè)方法了 invokeLater,
public void actionPerformed(ActionEvent e){
new Thread(new Runnable(){
//do something
SwingUtilities.invokeLater(new Runnable(){
pulic void run(){
//update the GUI
}
});
}).start;
}
這個(gè)方法的作用就是將一個(gè)更新界面的任務(wù)放到EDT中,EDT會(huì)在適當(dāng)?shù)臅r(shí)候進(jìn)行調(diào)用以更新界面。invokeLater負(fù)責(zé)創(chuàng)建一個(gè)含有Runnable的特定事件,并讓其在EDT中排隊(duì)等待調(diào)用,當(dāng)被調(diào)用時(shí)就會(huì)運(yùn)行Runnable中的run方法進(jìn)行派發(fā)。