简体   繁体   English

JProgressBar无法正常工作

[英]JProgressBar not working properly

So my JProgressBar I have set up doesn't work the way I want it. 因此,我设置的JProgressBar无法按照我想要的方式工作。 So whenever I run the program it just goes from 0 to 100 instantly. 因此,每当我运行该程序时,它就会立即从0变为100。 I tried using a ProgressMonitor , a Task, and tried a SwingWorker but nothing I tried works. 我尝试使用ProgressMonitor ,Task,并尝试了SwingWorker但没有任何尝试。

Here is my program: 这是我的程序:

int max = 10;
for (int i = 0; i <= max; i++) {
        final int progress = (int)Math.round(
            100.0 * ((double)i / (double)max)
        );

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    Logger.getLogger(BandListGenerator.class.getName()).log(Level.SEVERE, null, ex);
                }
                jProgressBar2.setValue(progress);
            }
        });
    }

@MadProgrammer Here is my attempt at making a swing worker and writing each name to the document and updating the progress bar. @MadProgrammer这是我尝试做一名摆动工作人员并将每个名称写入文档并更新进度栏的尝试。 The program gets to around 86 percent and stops, never creating the finished document. 该程序将达到86%左右并停止,从不创建完成的文档。 The program creates a blank document. 该程序将创建一个空白文档。 Here are the two methods first is the SwingWorker object I made: 这是我首先创建的SwingWorker对象,这是两种方法:

public class GreenWorker extends SwingWorker<Object, Object> {
    @Override
    protected Object doInBackground() throws Exception {
        int max = greenList.size();
        XWPFParagraph tmpParagraph;
        XWPFRun tmpRun;
        FileInputStream file = 
                new FileInputStream(location + "GreenBandList.docx");
        gDocument = new XWPFDocument(OPCPackage.open(file));
        for (int i = 0; i < max; i++) {
            tmpParagraph = gDocument.getParagraphs().get(0);
            tmpRun = tmpParagraph.createRun();
            if (greenList.get(i).length() == 1) {
                    tmpRun.setBold(true);
                    tmpRun.setText(greenList.get(i));
                    tmpRun.setBold(false);
            } else {
                    tmpRun.setText(greenList.get(i));//Write the names to the Word Doc
            }
            int progress = Math.round(((float) i / max) * 100f);
            setProgress(progress);
        }
        return null;
  }        
}

And here is the code for the button that starts it and has my property change event. 这是启动它并具有我的属性更改事件的按钮的代码。

private void GenerateGreenList() throws IOException, InterruptedException {
    //Need to fix the bug that removes the Letter Header in Yellow Band list
    //********************************************************************\\

    //Delete the old list and make a new one
    File templateFile = new File(location + "\\backup\\GreenTemplate.docx");
    FileUtils.deleteQuietly(new File(location + "GreenBandList.docx"));
    FileUtils.copyFile(templateFile, new File(location + 
            "GreenBandList.docx"));
    //Get the New Entries
    String[] entries = jTextPane3.getText().split("\n");
    for (String s : entries) {
        if (s != null) {
            greenList.add(s);
        }
    }
    //Resort the list
    Collections.sort(greenList);
    //Write the names to the document
    GreenWorker worker = new GreenWorker();
    worker.addPropertyChangeListener(new PropertyChangeListener() {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if ("progress".equals(evt.getPropertyName())) {
                jProgressBar2.setValue((Integer) evt.getNewValue());
            }
        }
    });
    worker.execute();
    if (worker.isDone()) {
        try {
            gDocument.write(new FileOutputStream(new File(location + "GreenBandList.docx")));
            ////////////////////////////////////////////////////////////
        } catch (IOException ex) {
            Logger.getLogger(BandListGenerator.class.getName()).log(Level.SEVERE, null, ex);
        }
        JOptionPane.showMessageDialog(null, "Green Band List Created!");
        jProgressBar2.setValue(0);
    }
}

I used the property change listener from one of your other posts but I don't really understand what the one you wrote does or what it does in general? 我从其他一篇文章中使用了属性更改侦听器,但是我真的不明白您写的内容是什么还是一般情况下的内容?

Swing is a single threaded environment, that is, there is a single thread which is responsible for processing all the events that occur within the system, including repaint events. Swing是一个单线程环境,也就是说,只有一个线程负责处理系统内发生的所有事件,包括重绘事件。 Should anything block this thread for any reason, it will prevent Swing from processing any new events, including, repaint events... 如果任何东西由于某种原因阻塞了该线程,它将阻止Swing处理任何新事件,包括重绘事件...

So all this ... 所以这一切...

EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            Logger.getLogger(BandListGenerator.class.getName()).log(Level.SEVERE, null, ex);        }
        jProgressBar2.setValue(progress);
    }
});

Is constantly pausing the Event Dispatching Thread, preventing it from actually doing any updates (or at least spacing them randomly)... 一直在暂停事件调度线程,以防止它实际进行任何更新(或至少将它们随机隔开)...

It's also likely that your outer loop is been run from within the context of the EDT, meaning that until it exists, nothing in the Event Queue will be processed. 您的外循环也很可能是在EDT上下文中运行的,这意味着直到存在外循环,事件队列中的任何内容都不会被处理。 All your repaint requests will be consolidated down to a single paint request and voila, instant filled progress bar... 您所有的重涂请求都将合并为一个重涂请求,瞧,即时填充进度栏...

You really should use a SwingWorker - I know you said you tried one, but you've not shown any code as to your attempt in this regards, so it's difficult to know why it didn't work, however... 您确实应该使用SwingWorker我知道您说过您尝试过一个,但是您没有在此方面显示任何代码来进行尝试,因此很难知道为什么它不起作用。

And forgive me if we haven't said this a few times before :P 如果我们之前没说过几次,请原谅我:P

You are evoking Thread.sleep inside the EvokeLater which means that it is running on another thread than your for loop. 您正在EvokeLater内部EvokeLater Thread.sleep ,这意味着它正在for循环之外的其他线程上运行。 ie, your for loop is completing instantaneously (well, however long it takes to loop from 1 to 100, which is almost instantaneously). 即,您的for循环是瞬时完成的(嗯,但是从1循环到100,这几乎是瞬时需要很长时间)。

Move Thread.sleep outside of EvokeLater and it should work as you intend. Thread.sleep EvokeLater之外,它应该可以正常工作。

    int max = 10;
    for (int i = 0; i <= max; i++) {
        final int progress = (int)Math.round(
            100.0 * ((double)i / (double)max)
        );

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                jProgressBar2.setValue(progress);
            }
        });
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            Logger.getLogger(BandListGenerator.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

Edit: agree with @MadProgrammer. 编辑:同意@MadProgrammer。 It appears this is just an illustrative question, but you should make sure whatever you're trying to accomplish here you use a SwingWorker for. 看来这只是一个说明性问题,但是您应该确保使用SwingWorker进行此处想要完成的任何事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM