如何停止SwingWorker?

时间:2012-03-05 09:26:04

标签: java swing swingworker

如何阻止SwingWorker开展工作?我知道有cancel()方法,但我能做的最多就是匿名创建一个正在完成工作的新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是一个与取消按钮事件不同的方法,所以我将无法调用Worker cancel()方法。

尝试让工人成为班级的一个属性而没有运气:

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

但是当我去的时候:

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

我得到不兼容的类型,发现无效,需要SwingWorker,而且我完全没有想法。

任何提示?

由于

2 个答案:

答案 0 :(得分: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();

修改

修复了进程中的错误:向模型添加行必须始终在批处理的第一个索引处开始,除非在处理标题时。

答案 1 :(得分:1)

1)永远不要创建/重新创建

DefaultTableModel modelo = new DefaultTableModel();

2)请问是什么

jTableResultados.removeAll();

JTable, AbstractTableModel, DefaultTableModel

3)你的JProgressBar无法正常工作

jProgressBar.setIndeterminate(false);

4)这两个链接问题使我与取消SwingWorker's实例

有关