java 板


LINE

※ 引述《gp123 (George Peng)》之銘言: : 這個問題很明顯是thread的問題, : 由於Swing元件的更新在另一個thread中進行, : 而這個thread的優先權很低。 : : 我發現函式只會自己跑自己的 : : 但JLabel完全沒有反應 : : 等到遞迴函式跑完了 : : Label才終於顯示最後的狀態 : : 可是中途完全沒有任何反應 : 在你的狀況中, : 幾乎要等到遞迴的method執行完後, : 才有機會輪到Swing一次更新到最新狀況, : 才會造成你看到的結果。 : 通常不建議在一般的worker thread中直接操作Swing, : 長時間的操作中更不合適, : 可試著參考 : http://slientfreaky.blogspot.tw/2011/09/java-swing.html : 的方式, : 將你的函式移到GUI的執行緒中進行。 通常 GUI 回應不夠及時(常見於提問中的說法是:中間變化略過直接顯示最後的 狀態),是由於在 UI Thread 做了耗時間的事,若這些事裡頭包含了操作 UI 組件 或變更組件資料/狀態,就會出現『常見說法』中的情況。 這不是由於 UI Thread 的 priority 太低所致。 原帖主希望在一個遞迴函式的執行過程中由 UI 組件顯示執行的狀態(也許是每一個 call stack 的參數或某些狀態),要這樣子做來幫助了解遞迴函式執行的流程(教學 用的程式?)勢必要在遞迴函式中加入 delay,否則程式執行的速度很快,肉眼是 無法觀察到過程中 UI 組件顯示的即時資訊(人的反應太慢)。 下面是一個以遞迴函式來做倒數的 demo(對,很矯情的 demo),它顯示出一般 要做一件耗時的事情又需要在過程中更新 UI 組件來顯示其 progress 的常見做法。 這只是一個用來點出某些觀念(我在上一篇的推文)的demo,所以暫時請不要講究 這倒數精不精確或其他小細節。 CountDownDemo.java(網頁版: http://ideone.com/VEY1io ) CountDown.java(網頁版: http://ideone.com/edwtgI ) *減少看官翻頁動作,註解(討論)寫在前頭,程式碼殿後 如果把 start 按鈕按下後的動作改成 counter.syncStart(10); 取代了原本的 counter.asyncStart(10); 這就是在 UI Thread(event-dispatching thread) 裡做耗時的工作(倒數需要 好幾秒),會導致倒數的期間(約 10 秒) GUI 像是死了一般(不會更新);直到 倒數完畢才直接顯示 0 秒。 =========================================================================== CountDown.java package cc.ptt; public class CountDown { public interface OnTickListener { public void onTick(int seconds); } private static class NullTickListener implements OnTickListener { @Override public void onTick(int seconds) { } } private static final OnTickListener nullListener = new NullTickListener(); private OnTickListener tickListener = nullListener; public void asyncStart(final int seconds) { // run in some worker thread new Thread(new Runnable() { public void run() { try { count(tickListener, seconds); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } public void syncStart(int seconds) { // run in the caller thread try { count(tickListener, seconds); } catch (InterruptedException e) { e.printStackTrace(); } } private void count(OnTickListener listener, int timeInSecs) throws InterruptedException { if (timeInSecs <= 0) { listener.onTick(0); return; } listener.onTick(timeInSecs); Thread.sleep(1000); count(listener, timeInSecs - 1); } public OnTickListener getTickListener() { return tickListener == nullListener ? null : tickListener; } public void setTickListener(OnTickListener tickListener) { if (tickListener == null) this.tickListener = nullListener; else this.tickListener = tickListener; } } =========================================================================== CountDownDemo.java package cc.ptt; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.SwingUtilities; public class CountDownDemo { public static void main(String[] args) { JFrame frm = new JFrame("Demo for Java@ptt"); frm.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); final JLabel messageBar = new JLabel("", JLabel.CENTER); messageBar.setBorder(BorderFactory.createLoweredBevelBorder()); messageBar.setFont(messageBar.getFont().deriveFont(48f)); frm.getContentPane().add(messageBar); final JButton start = new JButton("開始倒數 10 秒"); frm.getContentPane().add(start, BorderLayout.SOUTH); final CountDown counter = new CountDown(); counter.setTickListener(new CountDown.OnTickListener() { @Override public void onTick(int seconds) { // setText method is thread-safe messageBar.setText(String.format("%d 秒", seconds)); if (seconds <= 0) { SwingUtilities.invokeLater(new Runnable() { public void run() { start.setEnabled(true); } }); } } }); start.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { start.setEnabled(false); counter.asyncStart(10); // counter.syncStart(10); } }); frm.setSize(400, 400); frm.setLocationRelativeTo(null); frm.setVisible(true); } } --



※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 1.172.190.207 ※ 編輯: sbrhsieh 來自: 1.172.187.77 (01/04 01:31)







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:Gossiping站內搜尋

TOP