java 板


LINE

※ 引述《sbrhsieh (十年~)》之銘言: : 通常 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 ) 個人憑著久遠的錯誤印象,在未經查證的狀況下回覆。 很感謝sbrhsieh的回應,發現這問題,並提醒我將來要更謹慎。 以下參考自Java SE的官方文件 Swing's Threading Policy總結一下 Ref: http://docs.oracle.com/javase/7/docs/api/javax/swing/package-summary.html Swing元件並非thread-safe, 基本上所有更改Swing元件狀態的動作都應該要在Swing Thread中完成, 且不能花太長的時間執行,以免拖垮Swing元件的重繪。 但因為actionListener等AWT/Swing的event handling通常預設在Swing Thread中執行, 所以一般我們不會查覺到這問題, 通常問題會發生在: (1)當Dialog或Frame顯示後,仍直接在原本的worker thread中 (即沒有在event handler)中操作Swing component, 這可能會造成Swing元件不可預期的狀態。 (2)操作Swing執行時間太久,這會拖垮元件重繪/反應的時間, 此即原PO者的問題所在。 如果要在長時間的工作中操作Swing元件, 最好將操作Swing元件的部分單獨在Swing thread中執行, sbrshieh的作法即是標準作法, 而這會牽涉到Thread的建立/執行/溝通, 另一種作法是使用SwingWorker(詳情請見API說明), 可以省下自行操作執行緒的工作。 以下用SwingWorker改寫原s大的倒數計時程式, 功能差不多(但改成只能倒數一次,以集中問題焦點), 在部份程式碼加註與原寫法的不同: package swingworkertest; import java.util.List; 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.SwingWorker; public class CountDownDemo_SwingWorker { 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(10, messageBar); start.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { start.setEnabled(false); counter.execute(); // 原為 counter.asyncStart(10); // counter.get(); // 原為counter.syncStart(10); } }); frm.setSize(400, 400); frm.setLocationRelativeTo(null); frm.setVisible(true); } } class CountDown extends SwingWorker<Integer,Integer> { private int m_sec; private JLabel m_message; CountDown(int seconds, JLabel message) { m_sec = seconds; m_message = message; } @Override protected Integer doInBackground() throws Exception { count(m_sec); return 0; } private void count(int timeInSecs) throws InterruptedException { if (timeInSecs <= 0) { publish(0); // 原為 listener.onTick(0); return; } publish(timeInSecs); // 原為 listener.onTick(timeInSecs); Thread.sleep(1000); count(timeInSecs - 1); } // 以下原為 counter.setTickListener(new CountDown.OnTickListener() {...} @Override protected void process(List<Integer> intermediate_data) { if (!intermediate_data.isEmpty()) m_message.setText(String.format("%d 秒", intermediate_data.get(intermediate_data.size()-1))); } } --



※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.114.88.25
1F:推 popcorny:推這篇... SwingWorker好用 01/08 22:18
2F:→ sbrhsieh:可以完全不改CountDown class直接套進SwingWorker裡使用 01/11 23:55







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燈, 水草

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

TOP