Swing組件相關(guān)的操作
不靈敏的圖形用戶界面會(huì)降低應(yīng)用程序的可用性。當(dāng)以下現(xiàn)象出現(xiàn)的時(shí)候,我們通常說這個(gè)用戶界面反應(yīng)不靈敏:
◆不響應(yīng)事件的現(xiàn)象;
◆沒有更新的現(xiàn)象;
這些現(xiàn)象在很大程度上與事件的處理方法相關(guān),而在編寫Swing應(yīng)用程序的時(shí)候,我們幾乎必然要編寫方法去響應(yīng)鼠標(biāo)點(diǎn)擊按鈕,鍵盤回車等事件。在這些方法中我們要編寫一些代碼,在運(yùn)行時(shí)去觸發(fā)一些動(dòng)作。常見動(dòng)作包括查找,更新數(shù)據(jù)庫等。在這篇文章中通過對(duì)一個(gè)實(shí)例的分析,介紹了一些基本概念,常見的錯(cuò)誤以及提出了一個(gè)解決方案。
event-dispatching thread
我們一定要記住,事件響應(yīng)方法的代碼都是在event-dispatching thread中執(zhí)行的,除非你啟用另一個(gè)線程。
那么,什么是event-dispatching thread呢?單一線程規(guī)則:一旦一個(gè)Swing組件被實(shí)現(xiàn)(realized),所有的有可能影響或依賴于這個(gè)組件的狀態(tài)的代碼都應(yīng)該在event-dispatching thread中被執(zhí)行。而實(shí)現(xiàn)一個(gè)組件有兩種方式,對(duì)頂層組件調(diào)用show(), pack(), 或者setVisible(true)。
將一個(gè)組件加到一個(gè)已經(jīng)被實(shí)現(xiàn)的容器中。
單一線程規(guī)則的根源是由于Swing組件庫的大部分方法是對(duì)多線程不安全的。
為了支持單一線程模型,Swing組件庫提供了一個(gè)專門來完成這些與Swing組件相關(guān)的操作的線程,而這一線程就是event-dispatching thread。我們的事件響應(yīng)方法通常都是由這一線程調(diào)用的,除非你自己編寫代碼來調(diào)用這些事件響應(yīng)方法。在這里初學(xué)者經(jīng)常犯的一個(gè)錯(cuò)誤就是在事件響應(yīng)方法中完成過多的與修改組件沒有直接聯(lián)系的代碼。其最有可能的效果就是導(dǎo)致組件反應(yīng)緩慢。比如以下響應(yīng)按鈕事件的代碼:
- String str = null;
- this.textArea.setText("Please wait...");
- try {
- //do something that is really time consuming
- str = "Hello, world!";
- Thread.sleep(1000L);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- this.textArea.setText(str);
執(zhí)行之后的效果就是按鈕似乎定住了一段時(shí)間,直到Done.出現(xiàn)之后才彈起來。原因就是Swing組件的更新和事件的響應(yīng)都是在event-dispatching thread中完成的,而事件響應(yīng)的時(shí)候,event-dispatching thread被事件響應(yīng)方法占據(jù),所以組件不會(huì)被更新。而直到事件響應(yīng)方法退出時(shí)才有可能去更新Swing組件。
為了解決這個(gè)問題,有人也許會(huì)試圖通過調(diào)用repaint()方法來更新組件:
- final String[] str = new String[1];
- this.jTextArea1.setText("Please wait...");
- this.repaint();
- try {
- Thread.sleep(1000L);
- }catch(InterruptedException e) {
- e.printStackTrace();
- }
- str[0] = "Done.";
- jTextArea1.setText(str[0]);
【編輯推薦】