Filettatura barra di avanzamento MVC

Sto utilizzando un pattern MVC per il mio progetto, quando un utente preme il pulsante di ricerca, chiamo una ricerca nel modello, ma voglio anche aggiornare una barra di avanzamento con le informazioni restituite da quel modello.

Ho provato a utilizzare un oscillatore, ma la barra di avanzamento non si aggiorna. Sospetto che stia facendo qualcosa di sbagliato con il mio threading.

Il mio pulsante come definito nel controller è:

class SearchBtnListener implements ActionListener { public void actionPerformsd(ActionEvent e) { _view.displayProgress(); } } 

Questo chiama la ricerca nel modello e ha la seguente chiamata nella vista:

 public void displayProgress() { TwoWorker task = new TwoWorker(); task.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent e) { if ("progress".equals(e.getPropertyName())) { _progressBar.setValue((Integer) e.getNewValue()); } } }); task.execute(); } private class TwoWorker extends SwingWorker { @Override protected Void doInBackground() throws Exception { _model.startSearch(getTerm()); // time intensive code File file = new File("lock"); while (file.exists()){ setProgress(_model.getStatus()); System.out.println(_model.getStatus()); // never called } return null; } protected void done(){ updateMain(); } } 

Funzione fittizia definita in Model per il test:

 public int getStatus(){ Random r = new Random(); return r.nextInt(); } 

Non chiamare

 _progressBar.setValue(_model.getStatus()); 

dall’interno di SwingWorker poiché questo chiama il codice Swing da un thread in background ed è ciò che è in ogni caso PropertyChangeListener. Invece, basta impostare la proprietà di avanzamento, questo è tutto.

Inoltre, non chiamare done () dal metodo doInBackground poiché questo deve essere chiamato dall’EDT da SwingWorker. Quindi lascia che lo stesso SwingWorker chiami questo metodo quando è effettivamente fatto.

Inoltre, Done () dovrebbe essere fatto () – la prima lettera non deve essere maiuscola, e dovresti usare le annotazioni @Override in questo codice per essere sicuro che stai sovrascrivendo i metodi correttamente.

Inoltre, cosa fa questo?

  _model.startSearch(_view.getTerm()); 

Chiama il codice che richiede un po ‘di tempo per essere completato? Questo dovrebbe essere inizializzato all’interno dello stesso DoInBackground di SwingWorker?

Modifica: un’altra opzione consiste nel dare al modello una proprietà int legata, diciamo chiamata progresso, e quindi aggiungere un PropertyChangeListener direttamente aggiornandolo a JProgressBar. Per esempio,

 import java.awt.BorderLayout; import java.awt.event.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import javax.swing.*; public class MVC_ProgressBarThread { private static void createAndShowUI() { MVC_View view = new MVC_View(); MVC_Model model = new MVC_Model(); MVC_Control control = new MVC_Control(view, model); view.setControl(control); JFrame frame = new JFrame("MVC_ProgressBarThread"); frame.getContentPane().add(view); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } public static void main(String[] args) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { createAndShowUI(); } }); } } @SuppressWarnings("serial") class MVC_View extends JPanel { private MVC_Control control; private JProgressBar progressBar = new JProgressBar(); private JButton startActionButton = new JButton("Start Action"); public MVC_View() { startActionButton.addActionListener(new ActionListener() { public void actionPerformsd(ActionEvent e) { buttonActionPerformsd(); } }); JPanel buttonPanel = new JPanel(); buttonPanel.add(startActionButton); setLayout(new BorderLayout()); add(buttonPanel, BorderLayout.NORTH); add(progressBar, BorderLayout.CENTER); } public void setControl(MVC_Control control) { this.control = control; } private void buttonActionPerformsd() { if (control != null) { control.doButtonAction(); } } public void setProgress(int progress) { progressBar.setValue(progress); } public void start() { startActionButton.setEnabled(false); } public void done() { startActionButton.setEnabled(true); setProgress(100); } } class MVC_Control { private MVC_View view; private MVC_Model model; public MVC_Control(final MVC_View view, final MVC_Model model) { this.view = view; this.model = model; model.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent pce) { if (MVC_Model.PROGRESS.equals(pce.getPropertyName())) { view.setProgress((Integer)pce.getNewValue()); } } }); } public void doButtonAction() { view.start(); SwingWorker swingworker = new SwingWorker() { @Override protected Void doInBackground() throws Exception { model.reset(); model.startSearch(); return null; } @Override protected void done() { view.done(); } }; swingworker.execute(); } } class MVC_Model { public static final String PROGRESS = "progress"; private static final int MAX = 100; private static final long SLEEP_DELAY = 100; private int progress = 0; private PropertyChangeSupport pcs = new PropertyChangeSupport(this); public void setProgress(int progress) { int oldProgress = this.progress; this.progress = progress; PropertyChangeEvent evt = new PropertyChangeEvent(this, PROGRESS, oldProgress, progress); pcs.firePropertyChange(evt); } public void reset() { setProgress(0); } public void addPropertyChangeListener(PropertyChangeListener listener) { pcs.addPropertyChangeListener(listener); } public void startSearch() { for (int i = 0; i < MAX; i++) { int newValue = (100 * i) / MAX; setProgress(newValue); try { Thread.sleep(SLEEP_DELAY); } catch (InterruptedException e) {} } } }