Pass the execution of a given method to the SwingWorker as an argument

3

I have a small application in swing , where I would like to display a progress when certain actions are executed

As an example, I have the listener below that is executed when a JComboBox is changed. It takes the selected item (which in this case is a Setor object with id and name ), and passes the id pro CadastranteComboModel , which in turn searches the bank for the list of registrants of that last sector and displays in another JComboBox of registrants:

private void comboSetorItemStateChanged(java.awt.event.ItemEvent evt) {                                            
    if (evt.getStateChange() == ItemEvent.SELECTED) {
        final int setorId = ((Setor) evt.getItem()).getId();
        CadastranteComboModel cadComboModel = new CadastranteComboModel(setorId);
        comboUsuario.setModel(cadComboModel);

The problem is that this communication with the bank (which is in HSQL) takes a while because the application runs from a network location in Stand-alone mode. So I created a JDialog only to display an JProgressBar infinite, but I do not know how to pass the execution of the CadastranteComboModel cadComboModel = new CadastranteComboModel(setorId); line, for example, to SwingWorker in doInBackground() .

Attempting to work around this problem, I booted this code inside the% quoted%:

        SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
            // esta é a janela que fiz a parte
            //com a JProgressBar infinita
            ProgressDialog progress;

             //esse método que ativa o progresso pelo publish()
            // e executa a linha a seguir em uma Thread separada
            @Override
            protected Void doInBackground() throws Exception {
                publish();
                CadastranteComboModel cadComboModel = new CadastranteComboModel(setorId);
                comboUsuario.setModel(cadComboModel);
                return null;

            }

            @Override
            protected void process(List<Void> chunks) {
                // getInstance() é o frame da tela como referencia
                //esse método é "decorativo"
                changeStatusComponent(getInstance(), false);
                //chama e exibe a JDialog com a JProgressBar
                progress = new ProgressDialog(getInstance(), true);
                progress.setLocationRelativeTo(getInstance());
                progress.setVisible(true);
            }

            @Override
            protected void done() {
                //quando termina a execução no doInBackground
                // fecho a tela de progresso
                progress.dispose();
                changeStatusComponent(getInstance(), true); 
            }
        };
        worker.execute();

It works perfectly for the case, but I'm going to have to repeat the same block of code in another 7 or 8 methods (some even return values), which have some action that depends on query in the database, like this one that excludes an office of the table and the bank:

private void btnExcluirOficioActionPerformed(java.awt.event.ActionEvent evt) {                                                 
    int indiceRowModel = this.tabela.getRowSorter().convertRowIndexToModel(this.tabela.getSelectedRow());
    int intOf = (int) this.tabela.getModel().getValueAt(indiceRowModel, 0);
    Date date = (Date) this.tabela.getModel().getValueAt(indiceRowModel, 3);
    String strAno = new SimpleDateFormat("yyyy").format(date);
    String strSetor = (String) this.tabela.getModel().getValueAt(indiceRowModel, 5);
    String strOficio = strSetor + " " + intOf + "-" + strAno;

    int confirma = JOptionPane.showConfirmDialog(getInstance(), "Excluir o oficio " + strOficio + "?",
            ListaDeOficiosUI.TITULO, JOptionPane.YES_NO_OPTION);
    if (confirma == JOptionPane.YES_OPTION) {
        try {
            //por causa desta chamada, vou ter que inserir aquele bloco
            // do swingworker
            this.tableModel.removeRow(indiceRowModel);
            PrintMessageUI.exibirMsg(this.getInstance(), "Oficio" + strOficio + " excluído.");
        } catch (ExcecaoPadrao ex) {
            PrintMessageUI.exibirError(this, ex.getMessage());
        }
    }
}

What I need to do is a class that inherits from listener and can receive these "problematic" methods as arguments, passing them to swingworker , but I do not know how I can do this.

Is there any way to pass one method as an argument to another, and its execution not be performed on the call, but within the method that received it as an argument?

  

Note: the application (the jar, in this case) is in java7, I can not do it in java8   for IT restrictions (but suggestions in java8 are welcome).

    
asked by anonymous 28.03.2016 / 15:36

1 answer

3

If the methods you want to run in doInBackground() all have the same signature, the solution would be to declare an interface and pass it on to the constructor of a class inherited from SwingWorker .

public class Worker extends SwingWorker<Void, Void>{

    interface Operation{
        void execute(int valor); //Altere a assinatura de acordo com a sua necessidade
    }

    Operation operation;
    int valor;
    public Worker(Operation operation, int valor){

        this.operation = operation;
        this.valor = valor;
    }

    @Override
    protected Void doInBackground() throws Exception {

        operation.execute(valor);
    }

    @Override
    protected void process(List<Void> chunks) {

        -----
        -----
    }

    @Override
    protected void done() {

        -----
        -----
    }
}

Any class that implements the interface Operation can be passed in the constructor and its method executed in doInBackground() :

Worker worker = new Worker(myOperationClass, 10);
worker.execute();

As this does not happen, a possible solution will be, since what varies is just the code of doInBackground() , create an abstract class that inherits from SwingWorker and implement the process() and done() , leaving the doInBackground() method to be implemented.

public abstract class Worker extends SwingWorker<Void, Void>{

    //Implemente os métodos process e done

    @Override
    protected void process(List<Void> chunks) {

        -----
        -----
    }

    @Override
    protected void done() {

        -----
        -----
    }
}

When you need to run one of tasks create an instance of this class and then implement the doInBackground() method.

Worker worker = new Worker(){

    @Override
    protected Void doInBackground() throws Exception {

        //implemente de acordo com a situação.
    }
};
worker.execute();
    
28.03.2016 / 23:08