Не
progressBar.setValue(chunks.size() - 1);
Поскольку размер коллекции не тот, что вам нужен. Скорее, вы хотите, чтобы значение коллекции отображалось:
for (int item : chucks) {
progressBar.setValue(item);
}
Вам также необходимо вызвать get()
на своем работнике, когда он завершит свою работу, либо в методе done()
, либо в PropertyChangeListener. который уведомляет вас, когда значение состояния работника равно SwingWorker.StateValue.DONE
Тот же самый вызов get()
вернет новый объект InputAnalysis
в EDT и вызовет исключения, если они возникнут во время выполнения работника, так что вы можете обработайте их там.
например,
analyzeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Fizz fizz = fizzService.fetchFromWs(1234);
// make this guy final
final Analyzer analyzer = new Analyzer(progressBar, nameTextField.getText(), fizz);
analyzer.addPropertyChangeListener(evt -> {
// this is a call-back method and will be called in response to
// state changes in the SwingWorker
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
try {
// this is called on the EDT
InputAnalysis analysis = analyzer.get();
// do what you want with it here
} catch (Exception e) {
e.printStackTrace();
}
}
});
analyzer.execute();
// but now, how do I obtain the InputAnalysis instance?!
// InputAnalysis analysis = null; // analyzer.getSomehow();
}
}
(код не проверен)
Примечание: вы можете покончить с парой метода публикации / обработки, просто изменив связанное поле прогресса работника с любым значением от 0 до 100. Затем в том же PropertyChangeListener прослушивайте и отвечайте на изменения в этом свойстве.
Например, сортируйте ваш код, используя скелетный класс InputAnalysis:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
public class SwingWorkerExample {
private static void createAndShowGui() {
SwGui mainPanel = new SwGui();
JFrame frame = new JFrame("SwingWorker Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
@SuppressWarnings("serial")
class SwGui extends JPanel {
private JProgressBar progressBar = new JProgressBar(0, 100);
private JTextArea textArea = new JTextArea(14, 40);
private StartAction startAction = new StartAction("Start", this);
public SwGui() {
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton(startAction));
progressBar.setStringPainted(true);
textArea.setFocusable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
setLayout(new BorderLayout());
add(progressBar, BorderLayout.PAGE_START);
add(scrollPane);
add(bottomPanel, BorderLayout.PAGE_END);
}
public void appendText(String text) {
textArea.append(text + "\n");
}
public void setProgressValue(int value) {
progressBar.setValue(value);
}
}
@SuppressWarnings("serial")
class StartAction extends AbstractAction {
private SwGui gui;
private AnalyzerWorker worker;
private InputAnalysis inputAnalysis;
public StartAction(String text, SwGui gui) {
super(text);
this.gui = gui;
}
@Override
public void actionPerformed(ActionEvent e) {
worker = new AnalyzerWorker();
setEnabled(false); // turn off button
gui.appendText("START");
worker.addPropertyChangeListener(evt -> {
if (evt.getPropertyName().equals("progress")) {
int progress = (int) evt.getNewValue();
gui.setProgressValue(progress);
gui.appendText(String.format("Percent done: %03d%%", progress));
} else if (evt.getPropertyName().equals("state")) {
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
setEnabled(true);
try {
inputAnalysis = worker.get();
String analysisText = inputAnalysis.getText();
gui.appendText(analysisText);
} catch (InterruptedException | ExecutionException e1) {
e1.printStackTrace();
}
}
}
});
worker.execute();
}
}
class InputAnalysis {
public String getText() {
return "DONE";
}
}
class AnalyzerWorker extends SwingWorker<InputAnalysis, Void> {
private static final int MAX_VALUE = 100;
@Override
protected InputAnalysis doInBackground() throws Exception {
int value = 0;
setProgress(value);
while (value < MAX_VALUE) {
// create random values up to 100 and sleep for random time
TimeUnit.SECONDS.sleep((long) (2 * Math.random()));
value += (int) (8 * Math.random());
value = Math.min(MAX_VALUE, value);
setProgress(value);
}
return new InputAnalysis();
}
}
Что касается изменений в вашем вопросе и коде:
Вам необходим фоновый процесс, который может "Двусторонняя" беседа "с GUI, и для этого лучший способ, о котором я могу подумать, - это создать конечный автомат для фонового процесса, уведомив GUI, когда фоновый процесс изменяет состояние, через свойство смените слушателя и разрешите GUI ответить на это изменение. Я постараюсь показать вам решение кода, но это может занять некоторое время.