Как остановить SwingWorker? - PullRequest
       2

Как остановить SwingWorker?

2 голосов
/ 05 марта 2012

Как я могу остановить 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 cancel().

Попытка сделать работника атрибутом для класса безуспешно:

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

но потом, когда я иду на:

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

Я получаю несовместимые типы, найден недействительным, необходим SwingWorker, и у меня совершенно нет идей.

Какие-нибудь советы?

Спасибо

Ответы [ 2 ]

3 голосов
/ 05 марта 2012

Это не ответ на вопрос (как отменить, я думаю, что это решено), но как отделить фоновую обработку от обновлений вида / модели. Схема псевдокода:

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 голос
/ 05 марта 2012

1) никогда не создавать / заново создавать

DefaultTableModel modelo = new DefaultTableModel();

2) пожалуйста, что такое

jTableResultados.removeAll();

JTable, AbstractTableModel, DefaultTableModel

3) ваш JProgressBar не может работать

jProgressBar.setIndeterminate(false);

4) оба связанных вопроса заставляют меня задуматься в связи с отменой SwingWorker's instance

...