如何停止 SwingWorker? [英] How to Stop a SwingWorker?
问题描述
我怎样才能阻止 SwingWorker
做他的工作?我知道有 cancel()
方法,但我能做的最多就是匿名创建一个新的 SwingWorker
来完成这项工作.
How can I stop the SwingWorker
doing his work? I know there's the cancel()
method for that, but the most I could do is to anonymously create a new SwingWorker
that is doing the job.
以下是参考代码:
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();
}
实际上这项工作做得很好并且发布没有问题,但考虑到我使用数据库,可能会发生查询有太多结果并且完整发布所花费的时间,因此用户必须能够取消任务并运行新任务.
Actually the job is well done and published with no issues, but given that I work with a DB, it can happen that the query has too many results and the time taken for the full publish takes a time so the user has to be able to cancel the task and run a new one.
显然,worker 是一种与取消按钮事件不同的方法,所以我将无法调用 Worker cancel()
方法.
Obviously the worker is a different method than the cancel button event so I won't be able to invoke Worker cancel()
method.
尝试以这种方式使工人成为班级的属性,但没有运气:
Tried making the worker an attribute for the class with no luck this way:
public class myClass extends javax.swing.JFrame {
private SwingWorker<Void, Object[]> tarea;
但是当我去的时候:
tarea = new SwingWorker<Void,Object[]>(){...}
我得到了不兼容的类型,发现无效,需要 SwingWorker,而且我完全没有想法.
I get Incompatible types, found void, required SwingWorker, and I'm totally out of ideas.
有什么建议吗?
谢谢
推荐答案
这不是问题的答案(这是如何取消,我认为已经解决了)而是如何将后台处理与视图/模型更新分开.一个伪代码大纲:
This is not a answer to the question (which is how to cancel, I think that's solved) but how to separate the background handling from the view/model updates. A pseudo-code outline:
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();
编辑
修复了一个过程中的错误:向模型添加行必须始终从批处理的第一个索引开始,除非处理标题.
fixed a bug in process: adding rows to the model must start on first index of the batch always, except when processing the header.
这篇关于如何停止 SwingWorker?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!