簡體   English   中英

JProgressBar不可見,但進度正確更新

[英]JProgressBar is invisible but progress is updating correctly

我在此類中執行任務,對話框彈出為白色框。 print語句正在打印出我期望的進度值,但是直到操作完成后,對話框上才會顯示任何內容。 在對話框最后關閉之前,我可以看到進度條閃爍了毫秒。 絕對不知道發生了什么事:\\

    public class ProgressDialog extends JDialog {

    private JProgressBar pb;
    private SwingWorker<Boolean, Void> task;

    public SwingWorker<Boolean, Void> getTask(){
        return task;
    }

    public ProgressDialog(final String call){
        setTitle("Working...");
        setLayout(new BorderLayout());
        setBounds(300,300,300,100);
        pb = new JProgressBar(0, 100);
        pb.setValue(0);
        pb.setVisible(true);
        pb.setStringPainted(true);
        add(pb, BorderLayout.CENTER);
        setVisible(true);

        task = new SwingWorker<Boolean, Void>(){
            public Boolean doInBackground(){        
                switch(call){
                case "Category": pb.setValue(Category.getProgress());
                while(pb.getValue()<99){
                    try{
                        Thread.sleep(500);
                    } catch (InterruptedException e){
                        Thread.currentThread().interrupt();
                    }
                    pb.setValue(Category.getProgress());
                    System.out.println(pb.getValue());
                    repaint();
                    revalidate();
                }
                break;
                }
                return true;
            }
            public void done(){
                dispose();
            }
        };
    }
}

編輯:嘗試此更改。 沒有骰子。 為什么我什至沒有獲得0%的進度條? 只有在達到100%時才會顯示

public class ProgressDialog extends JDialog {

private JProgressBar pb;
private SwingWorker<Boolean, Integer> task;

public SwingWorker<Boolean, Integer> getTask(){
    return task;
}

public ProgressDialog(final String call){
    setTitle("Working...");
    setLayout(new BorderLayout());
    setBounds(300,300,300,100);
    pb = new JProgressBar(0, 100);
    pb.setValue(0);
    pb.setStringPainted(true);
    add(pb, BorderLayout.CENTER);
    setVisible(true);

    task = new SwingWorker<Boolean, Integer>(){
        public Boolean doInBackground(){        
            switch(call){
            case "Category": setProgress(Category.getProgress());
            while(pb.getValue()<99){
                try{
                    Thread.sleep(500);
                } catch (InterruptedException e){
                    Thread.currentThread().interrupt();
                }
                setProgress(Category.getProgress());
            }
            break;
            }
            return true;
        }

        public void done(){
            //dispose();
        }
    };

    task.addPropertyChangeListener(new PropertyChangeListener() {
                public  void propertyChange(PropertyChangeEvent evt) {
                    if ("progress".equals(evt.getPropertyName())) {
                        System.out.println((Integer)evt.getNewValue());
                        pb.setValue((Integer)evt.getNewValue());
                        pb.revalidate();
                        pb.repaint();
                    }
                }
            });
}

}

您正在嘗試通過SwingWorker的doInBackground方法中的后台線程設置進度條的狀態-這沒有任何意義。 使用SwingWorker的全部原因是允許您在Swing GUI中執行后台進程,因此您不會從后台線程進行Swing調用,也不會將Swing線程與長線程捆綁在一起。運行代碼。

您不應從此后台進程進行Swing調用。 而是使用publish / process方法,因為這些教程將向您展示。 或許更好的方法是,設置SwingWorker的progress字段,並在SwingWorker上使用PropertyChangeListener來允許進度欄對其做出反應。

無論如何,最重要的是:

  • 使用SwingWorker進行后台工作。
  • 不要從SwingWorker的doInBackground方法中進行Swing調用。
  • 使用發布將數據從后台方法推送到Swing線程領域。
  • 使用處理方法來處理要推送的數據。
  • SwingWorker具有一個progress屬性,該屬性也很方便用於允許Swing代碼響應后台狀態的更改。
  • 如果走這條路線,請使用PropertyChangeListener。
  • 您幾乎永遠都不想使用setBounds(...)或null布局。 作為一個寫過數百個Swing程序的人,請相信我,這個程序最終會咬住您的。
  • 看起來您的類別正在使用靜態方法來獲取進度。 同樣,這是您幾乎永遠不想做的事情。 進度字段建議state ,這應該是對象實例字段的一部分,絕不能是靜態的。

這是一個SSCCE,以演示如何更新JProgressBar 復制/粘貼並運行它。

注意,我們如何通過調用publish(i)來更新進度條,該publish(i)將整數發送到process()方法。 SwingWorker將結果以塊的形式發送到process()方法,但是我們僅使用Integer來更新JProgressBar因此我們只關心LAST塊。 在此SSCCE中,我們從1-1000開始。 如果您檢查控制台,您會發現跳過了1-1000之間的許多數字,因為我們更新得太快了, SwingWorker無法趕上(但是沒關系。這就是為什么它將結果成塊發送的原因)。

注意: process()方法最初是為程序員設計的,可以從他們長期運行的過程中返回實時結果並更新GUI。 因此,如果要進行數據庫訪JTable ,則可以使用返回的結果更新JTable 不過,我討厭那樣做。 因此,在99%的時間中,我只使用“不確定” JProgressBar並等待直到done()方法發布我的結果。 但是,有時候,我將使用“確定的” JProgressBar並像在本SSCCE中一樣進行更新。 我從來沒有使用過process()返回和發布實際數據。 :)但是,這就是它最初設計的目的。

import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

/**
 *
 * @author Ryan
 */
public class Test {

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                go();
            }
        });
    }

    public static void go() {
        JFrame frame = new JFrame();
        JProgressBar jpb = new JProgressBar();
        jpb.setIndeterminate(false);
        int max = 1000;
        jpb.setMaximum(max);
        frame.add(jpb);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        new Task(jpb, max).execute();
    }

    static class Task extends SwingWorker<Void, Integer> {

        JProgressBar jpb;
        int max;
        public Task(JProgressBar jpb, int max) {
            this.jpb = jpb;
            this.max = max;
        }

        @Override
        protected void process(List<Integer> chunks) {
            jpb.setValue(chunks.get(chunks.size()-1)); // The last value in this array is all we care about.
            System.out.println(chunks.get(chunks.size()-1));
        }

        @Override
        protected Void doInBackground() throws Exception {
            for(int i = 0; i < max; i++) {
                Thread.sleep(10); // Sleep for 1/10th of a second
                publish(i);
            }
            return null;
        }

        @Override
        protected void done() {
            try {
                get();
                JOptionPane.showMessageDialog(jpb.getParent(), "Success", "Success", JOptionPane.INFORMATION_MESSAGE);
            } catch (ExecutionException | InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

編輯:我創建了一個圖,該圖應該是處理SwingWorker時的有用參考,以便您知道將代碼放置在何處。

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM