1

(Ignore following sentence - I was being dumb). I have a feeling that I am calling the updates to my jProgressBar on the EDT (which I know is wrong).

@Action
public Task launchScenario() {

    return new LaunchScenarioTask(getApplication());
}

private class LaunchScenarioTask extends org.jdesktop.application.Task<Object, Void> {

    LaunchScenarioTask(org.jdesktop.application.Application app) {
        super(app);
        launchTestCaseButton.setEnabled(false);
        progressBar.setIndeterminate(false);
        statusPanel.validate();
        statusPanel.repaint();
        totalTests = scenarioRepeat * selectedSSIDS.length;
        setProgress(0);
    }

    @Override
    protected Object doInBackground() {
        currentScenario = 1;

        progressBar.setMaximum(totalTests);
        progressBar.setMinimum(0);

        try {
            Thread.sleep((long) 500);
        } catch (InterruptedException ignore) {
        }

        int ssidsToTest = selectedSSIDS.length;

        //For every SSID, we iterate through and create an autoconnector object
        for (int counter = 0; counter < ssidsToTest; counter++) {

            try {
                setMessage("Preparing " + selectedSSIDS[counter] + " test case...");
                Thread.sleep((long) 2000);
            } catch (InterruptedException ignore) {
            }

            setMessage("Launching ");
            AutoConnector ac = new AutoConnector(selectedSSIDS[counter]);

            for (int i = 0; i < scenarioRepeat; i++) {
                if (ac.connected()) {
                    setMessage("Running test " + currentScenario + "/" + totalTests);
                    currentScenario++;
                    passedTests++;
                } else {
                    currentScenario++;
                    failedTests++;
                }

                System.out.println("setting progress");
                setProgress((currentScenario / totalTests) * 100);
                progressBar.setString((currentScenario / totalTests) * 100 + "% complete");
            }

        }
        try {
            Thread.sleep((long) 500);
        } catch (InterruptedException ignore) {
        }
        return null;  // return your result
    }

    @Override
    protected void succeeded(Object result) {
        launchTestCaseButton.setEnabled(true);
        setMessage("Complete. " + passedTests + " tests passed and "
                + failedTests + " tests failed.");
    }
}

I know for a fact (and feel a bit bad) that I'm calling the updates (setProgress() and setMessage() in the doInBackground() method, and I have a sneaking suspicious that I should not be. <<

So the question is, where should I place the setProgress() snippets in the code? Would this require me creating a task with the AutoConnector class and seeing if I can update the jProgressBar from there?

I have used jProgressBars before, but not in this manner with NetBeans.

Andrew
  • 42
  • 8
  • You state, `"I have a feeling that I am calling the updates to my jProgressBar on the EDT (which I know is wrong)."` -- and just the opposite is true. Almost all calls that change Swing component state should be made ***on*** the EDT. – Hovercraft Full Of Eels Jun 13 '14 at 16:44
  • Ah, thank you for the correction. More than happy to learn! So since I can't call updates to the EDT in the method `doInBackground()` as stated by the autogenerated code, where should I place EDT updates? – Andrew Jun 13 '14 at 16:46

1 Answers1

1

Your problem is just the opposite of what you state at the beginning of your question. You state:

I have a feeling that I am calling the updates to my jProgressBar on the EDT (which I know is wrong).

And just the opposite is true. All updates to the JProgressBar should be made on the EDT, and you're doing just the opposite. You should call no methods on your JProgressBar from within your SwingWorker's doInBackground(...) method.

Instead consider

  • changing a listened to property such as your SwingWorker's progress property, and have the JProgressBar get updated in a PropertyChangeListener that listens for changes to this property, or
  • Use SwingWorker's publish/process method pair allow you to transmit data from the SwingWorker to your GUI on the EDT.

Myself, I much prefer adding a PropertyChangeListener to my SwingWorker (on the EDT), and updating my JProgressBar from within this listener. I feel that it allows for better code separation with lower coupling and higher cohesion than the first option.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Ah yes. I actually wasn't thinking and I meant I was calling updates to the EDT in the working thread. Terribly sorry about any confusion. I'll be doing some more research into the publish/process methods you suggested and report back. Thanks for your input! – Andrew Jun 13 '14 at 16:52
  • I was able to get it to partially work! My progress bar is stuck in indeterminate mode, and before I enter the working thread, I call `progressBar.setIndeterminate(false);`. What do you suggest I do? – Andrew Jun 13 '14 at 17:50
  • @Andrew: debug your problem. – Hovercraft Full Of Eels Jun 13 '14 at 18:05
  • I figured it out - I was using setValue instead of setProgress. I have to figure out the done() or succeeded() method next, but I'm confident I'll be able to do it. I also followed your advice and took a read on PropertyChangeListener. It's a bit out of my understanding, but I noticed that this is what Netbeans auto-generates. I have a much greater understanding of ProgressMonitors now! Once again, thank you. – Andrew Jun 13 '14 at 18:44