Swing 更新

      在〈Swing 更新〉中尚無留言

長時間禁用UI 主執行緒

在UI 中, 若每隔一最時間就要更新, 比如計時器, 就千萬別在UI主執行緒執行迴圈, 否則整個UI就會被卡住

非UI執行緒更新畫面

在Java中, 是可以在別的執行緒使用setText來更新UI, 也保証是安全的. 但這也僅限於JLabel而以, 且官方文件並沒有說明, 那些是安全的, 那些是不安全的. 再加上Andorid, C#都是禁止非UI主行緒進行畫面更新, 所以並不建議此法.

SwingUtilities invokeLater

此法是產生一個執行緒, 稱為UIThread, 畫面的更新放在run裏面, 但我們並不使用 start()產生新執行緒來更新. 而是將此執行緒放在SwingUtilities.invokeLater()裏面. 待UI主執行緒有空時, 使用UI主執行緒來執行. 此法是最正確的作法. 程式碼如下

    private void btnActionPerformed(java.awt.event.ActionEvent evt) {                                         
        new Thread(new Runnable(){
            @Override
            public void run() {
                while(true){
                    try {Thread.sleep(10);} catch (InterruptedException ex) {}
                    SwingUtilities.invokeLater(new UiThread(timer++));
                }
            }
        }).start();
    }
    class UiThread extends Thread{
        int value;
        public UiThread(int v){
            value=v;
        }
        public void run(){
            lbl.setText(String.valueOf(value));
        }
    }

Lambda

當然, 如果懂得Lambda的話, 上面藍色的部份就可以改成如下, 然後 class UIThread就可以整個拿掉.

    SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss:SSS");
    boolean runFlag=false;
    private void btnActionPerformed(java.awt.event.ActionEvent evt) {                                    
        runFlag=!runFlag;
        new Thread(()->{
            while(runFlag){
                try {Thread.sleep(1);} catch (InterruptedException ex) {}
                SwingUtilities.invokeLater(()->lbl.setText(sdf.format(new Date())));
            }
        }).start();
    } 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *