2012-03-05 48 views
2

如何停止SwingWorker的工作?我知道那裏有cancel()方法,但我能做的最多的是匿名創建一個新的SwingWorker正在完成這項工作。如何停止SwingWorker?

這裏是參考代碼:

public void mostrarResultado(final ResultSet resultado) { 

    new SwingWorker<Void, Object[]>() { 

     @Override 
     public Void doInBackground() { 

      // TODO: Process ResultSet and create Rows. Call publish() for every N rows created.+ 
      DefaultTableModel modelo = new DefaultTableModel(); 
      jTableResultados.removeAll(); 
      int columnas; 
      int res = 0; 
      try { 
       ResultSetMetaData metadata = resultado.getMetaData(); 
       columnas = metadata.getColumnCount(); 
       Object[] etiquetas = new Object[columnas]; 
       jProgressBar.setIndeterminate(true); 
       for (int i = 0; i < columnas; i++) { 
        etiquetas[i] = 
          metadata.getColumnName(i + 1); 
       } 
       modelo.setColumnIdentifiers(etiquetas); 
       jTableResultados.setModel(modelo); 

       while (resultado.next() && !this.isCancelled()) { 
        res++; 
        Object fila[] = new Object[columnas]; 
        for (int i = 0; i < columnas; i++) { 
         fila[i] = resultado.getObject(i + 1); 
        } 
        modelo.addRow(fila); 
        publish(fila); 
       } 
       jProgressBar.setIndeterminate(false); 
       if (res == 0) { 
        JOptionPane.showMessageDialog(jPanelClientes.getParent(), "No se encontraron resultados con los criterios de búsqueda definidos", "Sin resultados", JOptionPane.INFORMATION_MESSAGE); 
       } 
      } catch (SQLException ex) { 
       LOG.log(Level.SEVERE, "Excepcion: ", ex); 
       JOptionPane.showMessageDialog(jPanelClientes.getParent(), "Error en al ejecutar la busqueda seleccionada", "Error", JOptionPane.ERROR_MESSAGE); 
      } 
      return null; 
     } 
    }.execute(); 
} 

其實作業做得很好,沒有問題發表,但因爲我有一個數據庫工作,它可以發生在查詢結果過多和完整發布所花費的時間需要一段時間,因此用戶必須能夠取消該任務並運行新任務。

顯然,工作人員是一種不同於取消按鈕事件的方法,所以我將無法調用Worker cancel()方法。

試圖使工人的階級屬性,沒有運氣這樣:

public class myClass extends javax.swing.JFrame { 
     private SwingWorker<Void, Object[]> tarea; 

但後來當我去:

tarea = new SwingWorker<Void,Object[]>(){...} 

我得到的不兼容的類型,發現無效的,需要的SwingWorker ,我完全沒有想法。

任何提示?

感謝

+0

另請參見http://stackoverflow.com/questions/6113944/how-cancel-the-execution-of-a-swingworker – DNA 2012-03-05 09:31:11

+0

可能重複的[停止/取消SwingWorker線程?](http://stackoverflow.com/questions/8083768/stop-cancel-swingworker-thread) – DNA 2012-03-05 09:31:44

+0

確實可能重複,太糟糕了,搜索沒有彈出答案:/ – Lowb 2012-03-05 09:40:06

回答

3

這不是一個問題的答案(這是如何取消,我認爲這是解決了),但如何從視圖/模型更新分開後臺處理。僞碼概述:

public static class MyDBWorker extends SwingWorker<Void, Object[]> { 

    private JTable table; 
    private DefaultTableModel model; 
    private ResultSet resultado; 

    public MyDBWorker(JTable table, ResultSet resultado) { 
     this.table = table; 
     this.resultado = resultado; 
    } 

    @Override 
    protected Void doInBackground() throws Exception { 
     ResultSetMetaData metadata = resultado.getMetaData(); 
     int columnas = metadata.getColumnCount(); 
     Object[] etiquetas = new Object[columnas]; 
     for (int i = 0; i < columnas; i++) { 
      etiquetas[i] = metadata.getColumnName(i + 1); 
     } 
     publish(etiquetas); 
     while (resultado.next() && !this.isCancelled()) { 
      Object fila[] = new Object[columnas]; 
      for (int i = 0; i < columnas; i++) { 
       fila[i] = resultado.getObject(i + 1); 
      } 
      publish(fila); 
     } 
     return null; 
    } 


    @Override 
    protected void process(List<Object[]> chunks) { 
     int startIndex = 0; 
     // first chunk, set up a new model 
     if (model == null) { 
      model = new DefaultTableModel(); 
      model.setColumnIdentifiers(chunks.get(0)); 
      table.setModel(model); 
      startIndex = 1; 
     } 
     for (int i = startIndex; i < chunks.size(); i++) { 
      model.addRow(chunks.get(i)); 
     } 
    } 

    @Override 
    protected void done() { 
     // nothing to do, we were cancelled 
     if (isCancelled()) return; 
     // check for errors thrown in doInBackground 
     try { 
      get(); 
      // all was well in the background thread 
      // check if there are any results 
      if (table.getModel().getRowCount() == 0) { 
       // show message 
      } 
     } catch (ExecutionException e) { 
      // we get here if f.i. an SQLException is thrown 
      // handle it as appropriate, f.i. inform user/logging system 
     } catch (InterruptedException e) { 
      // 
     } 
    } 

} 

// use it 
SwingWorker worker = new MyDBWorker(table, resultado); 
PropertyChangeListener stateListener = new PropertyChangeListener() { 

    @Override 
    public void propertyChange(PropertyChangeEvent e) { 
     if (e.getNewValue() == SwingWorker.StateValue.STARTED) { 
      progressBar.setIndeterminate(true); 
     } 
     if (e.getNewValue() == SwingWorker.StateValue.DONE) { 
      progressBar.setIndeterminate(false); 
     } 

    } 

}; 
worker.addPropertyChangeListener(doneListener); 
worker.execute(); 

編輯

修正了在處理:添加行到模型必須在該批次的第一索引始終啓動,處理所述報頭時除外。

+0

感謝提示@kleopatra。我想是不是發佈(fila),我應該爲每個想要發佈的行調用進程(fila)? – Lowb 2012-03-05 16:17:13

+0

@Lowb不會 - 真正讓人大腦思考的一件事是線程的清晰分離:一些方法被設計爲在後臺線程上調用(fi doInBackground,發佈),而其他方法則保證在EDT上執行(fi過程,完成)。千萬不要混淆這個組的方法與其他組的方法 – kleopatra 2012-03-05 16:28:01

+0

嗯我不明白@kleopatra,process()被調用的時候呢?大塊的內容是什麼?我怎樣才能決定何時在用戶界面中顯示行?太多的問題,對不起: – Lowb 2012-03-05 16:39:50

1

1)永遠不會創建/ re_create

DefaultTableModel modelo = new DefaultTableModel(); 

2)請什麼

jTableResultados.removeAll(); 

JTable, AbstractTableModel, DefaultTableModel 

3)你的JProgressBar不能作品

jProgressBar.setIndeterminate(false); 

4 )都鏈接任務離子使我在與取消連接SwingWorker's實例

+0

1)那麼我應該如何定義tablemodel? 2)刪除之前在jTable中顯示的結果,顯示BD查詢的結果3)進度條工作正常。 4)解決了它,是的。 – Lowb 2012-03-05 10:00:49