Threads + JDialog - Dúvidas de como usar corretamente

A exceção acontece porque você está alterando uma coleção (adicionando ou removendo itens) enquanto itera usando um enhanced for ou um Iterator.

Posta o código completo da classe que fica fácil te mostrar como resolver o problema.

Estou usando uma LinkedList e via thread de monitoramento vou adicionando os eventos disparados.

public class CLPMonitor {

    private Protocol protocol;
    private List<CLPListener> listeners = new LinkedList<CLPListener>();
    private static CLPMonitor eagerInstance = null;

    public static synchronized CLPMonitor getEagerInstance() {
        if (eagerInstance == null) {
           eagerInstance = new CLPMonitor();
        }
        return eagerInstance;
    }

    private CLPMonitor() {

    }

    public void start() {
        clpMonitor();
    }

    public void addCLPListener(CLPListener listener) {
        listeners.add(listener);
    }

    public void clpMonitor() {
        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    while (true) {
                        if (protocol.readBoolean(4099, 2)) {
                            for (CLPListener listener : listeners) {
                                listener.machineReference(new CLPEvent(4099, 2));
                            }
                        } else {
                            for (CLPListener listener : listeners) {
                                listener.machineReferenceOff(new CLPEvent(4099, 2));
                            }
                        }

                        if (protocol.readBoolean(4099, 9)) {
                            for (CLPListener listener : listeners) {
                                listener.generalEmergency(new CLPEvent(4099, 9));
                            }
                        } else {
                            for (CLPListener listener : listeners) {
                                listener.generalEmergencyLiberate(new CLPEvent(4099, 9));
                            }
                        }

                        if (protocol.readBoolean(4140, 6)) {
                            for (CLPListener listener : listeners) {
                                listener.engineOverload(new CLPEvent(4140, 6));
                            }
                        }

                        if (protocol.readBoolean(4099, 8)) {
                            for (CLPListener listener : listeners) {
                                listener.failedMachine(new CLPEvent(4099, 8));
                            }
                        }

                        if (!protocol.readBoolean(4100, 2)) {
                            for (CLPListener listener : listeners) {
                               listener.tablePositioning(new CLPEvent(4100, 2));
                            }
                        }

                        if (protocol.readBoolean(4100, 7)) {
                             for (CLPListener listener : listeners) {
                                 listener.positionTable(new CLPEvent(4100, 7));
                             }
                        }

                        if (protocol.readBoolean(4100, 4) && !protocol.readBoolean(4099, 9)) {
                             for (CLPListener listener : listeners) {
                                 listener.securityCurtain(new CLPEvent(4100, 4));
                             }
                        } else {
                             for (CLPListener listener : listeners) {
                                 listener.securityCurtainLiberate(new CLPEvent(4100, 4));
                             }
                        }
                            }
                        }

                        if (protocol.readBoolean(4099, 6)) {
                            for (CLPListener listener : listeners) {
                                listener.feedPositionOK(new CLPEvent(4099, 6));
                            }
                        }

                        if (protocol.readBoolean(4099, 15)) {
                            for (CLPListener listener : listeners) {
                                listener.machineStopped(new CLPEvent(4099, 15));
                            }
                        } else {
                            for (CLPListener listener : listeners) {
                                listener.machineInMotion(new CLPEvent(4099, 15));
                            }
                        }

                        if (protocol.readBoolean(4100, 3)) {
                            for (CLPListener listener : listeners) {
                                listener.resetFailed(new CLPEvent(4100, 3));
                            }
                        } else {
                            for (CLPListener listener : listeners) {
                                listener.resetFailedOff(new CLPEvent(4100, 3));
                            }
                        }

                        if (protocol.readBoolean(4099, 14)) {
                            for (CLPListener listener : listeners) {
                                listener.machineOK(new CLPEvent(4099, 14));
                            }
                        } else {
                            for (CLPListener listener : listeners) {
                                listener.machineOFF(new CLPEvent(4099, 14));
                            }
                        }
                    }

                } catch (Exception e) {
                    
                }
            }
        });
        thread.start();
    }
}

Alguma classe está chamando o método addCLPListener enquanto sua Thread está processando um dos inúmeros for (CLPListener listener : listeners).

Quando eu implemento classes que podem receber vários listeners, eu não utilizo coleções, eu implemento o padrão de projeto Composite com a interface do listener.

O próprio Swing e AWT utilizam essa estratégia através da classe AWTEventMulticaster.
O benefício é que a implementação fica mais limpa, pois acaba com a necessidade de iterar listas de listeners.

No seu caso, vamos criar a classe CLPEventMulticaster, conforme abaixo:

final class CLPEventMulticaster implements CLPListener {

    protected static CLPListener add(CLPListener atual, CLPListener proximo) {
        if (atual == null) {
            return proximo;
        }
        if (proximo == null) {
            return atual;
        }
        return new CLPEventMulticaster(atual, proximo);
    }

    protected static CLPListener remove(CLPListener atual, CLPListener anterior) {
        if (atual == anterior || atual == null) {
            return null;
        }
        if (atual instanceof CLPEventMulticaster) {
            return ((CLPEventMulticaster) atual).remove(anterior);
        }
        return atual;
    }

    private final CLPListener a;
    private final CLPListener b;

    private CLPEventMulticaster(CLPListener a, CLPListener b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public void engineOverload(CLPEvent clpEvent) {
        a.engineOverload(clpEvent);
        b.engineOverload(clpEvent);
    }

    @Override
    public void failedMachine(CLPEvent clpEvent) {
        a.failedMachine(clpEvent);
        b.failedMachine(clpEvent);
    }

    @Override
    public void feedPositionOK(CLPEvent clpEvent) {
        a.feedPositionOK(clpEvent);
        b.feedPositionOK(clpEvent);
    }

    @Override
    public void generalEmergency(CLPEvent clpEvent) {
        a.generalEmergency(clpEvent);
        b.generalEmergency(clpEvent);
    }

    @Override
    public void generalEmergencyLiberate(CLPEvent clpEvent) {
        a.generalEmergencyLiberate(clpEvent);
        b.generalEmergencyLiberate(clpEvent);
    }

    @Override
    public void machineInMotion(CLPEvent clpEvent) {
        a.machineInMotion(clpEvent);
        b.machineInMotion(clpEvent);
    }

    @Override
    public void machineOFF(CLPEvent clpEvent) {
        a.machineOFF(clpEvent);
        b.machineOFF(clpEvent);
    }

    @Override
    public void machineOK(CLPEvent clpEvent) {
        a.machineOK(clpEvent);
        b.machineOK(clpEvent);
    }

    @Override
    public void machineReference(CLPEvent clpEvent) {
        a.machineReference(clpEvent);
        b.machineReference(clpEvent);
    }

    @Override
    public void machineReferenceOff(CLPEvent clpEvent) {
        a.machineReferenceOff(clpEvent);
        b.machineReferenceOff(clpEvent);
    }

    @Override
    public void machineStopped(CLPEvent clpEvent) {
        a.machineStopped(clpEvent);
        b.machineStopped(clpEvent);
    }

    @Override
    public void positionTable(CLPEvent clpEvent) {
        a.positionTable(clpEvent);
        b.positionTable(clpEvent);
    }

    @Override
    public void resetFailed(CLPEvent clpEvent) {
        a.resetFailed(clpEvent);
        b.resetFailed(clpEvent);
    }

    @Override
    public void resetFailedOff(CLPEvent clpEvent) {
        a.resetFailedOff(clpEvent);
        b.resetFailedOff(clpEvent);
    }

    @Override
    public void securityCurtain(CLPEvent clpEvent) {
        a.securityCurtain(clpEvent);
        b.securityCurtain(clpEvent);
    }

    @Override
    public void securityCurtainLiberate(CLPEvent clpEvent) {
        a.securityCurtainLiberate(clpEvent);
        b.securityCurtainLiberate(clpEvent);
    }

    @Override
    public void tablePositioning(CLPEvent clpEvent) {
        a.tablePositioning(clpEvent);
        b.tablePositioning(clpEvent);
    }

    private CLPListener remove(CLPListener listener) {
        if (listener == a) {
            return b;
        }
        if (listener == b) {
            return a;
        }
        CLPListener primeiro = remove(a, listener);
        CLPListener segundo = remove(b, listener);
        if (primeiro == a && segundo == b) {
            return this;
        }
        return add(primeiro, segundo);
    }
}

E agora vamos modificar a classe CLPMonitor para ter somente um atributo do tipo CLPListener:

public class CLPMonitor {

    private Protocol protocol;
    
    // mesmo quando houver mais de um listener
    // para essa classe é como se fosse um só objeto
    // é a magia do padrão Composite
    private CLPListener listener;
    
    private static CLPMonitor eagerInstance;

    public static synchronized CLPMonitor getEagerInstance() {
        if (eagerInstance == null) {
            eagerInstance = new CLPMonitor();
        }
        return eagerInstance;
    }

    private CLPMonitor() {}

    public void start() {
        clpMonitor();
    }

    public void addCLPListener(CLPListener listener) {
        // aqui acontece a mágica ao adicionar listeners
        this.listener = CLPEventMulticaster.add(this.listener, listener);
    }

    public void removeCLPListener(CLPListener listener) {
        // se quiser remover um listener, também pode
        this.listener = CLPEventMulticaster.remove(this.listener, listener);
    }

    public void clpMonitor() {
        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    while (true) {
                        if (listener == null) {
                            // se não há listeners
                            // dá uma chance pras outras Threads
                            // e volta pro início 
                            Thread.yield();
                            continue;
                        }
                        // Veja que maravilha: não há mais loops!!!
                        if (protocol.readBoolean(4099, 2)) {
                            listener.machineReference(new CLPEvent(4099, 2));
                        } else {
                            listener.machineReferenceOff(new CLPEvent(4099, 2));
                        }

                        if (protocol.readBoolean(4099, 9)) {
                            listener.generalEmergency(new CLPEvent(4099, 9));
                        } else {
                            listener.generalEmergencyLiberate(new CLPEvent(4099, 9));
                        }

                        if (protocol.readBoolean(4140, 6)) {
                            listener.engineOverload(new CLPEvent(4140, 6));
                        }

                        if (protocol.readBoolean(4099, 8)) {
                            listener.failedMachine(new CLPEvent(4099, 8));
                        }

                        if (!protocol.readBoolean(4100, 2)) {
                            listener.tablePositioning(new CLPEvent(4100, 2));
                        }

                        if (protocol.readBoolean(4100, 7)) {
                            listener.positionTable(new CLPEvent(4100, 7));
                        }

                        if (protocol.readBoolean(4100, 4) && !protocol.readBoolean(4099, 9)) {
                            listener.securityCurtain(new CLPEvent(4100, 4));
                        } else {
                            listener.securityCurtainLiberate(new CLPEvent(4100, 4));
                        }

                        if (protocol.readBoolean(4099, 6)) {
                            listener.feedPositionOK(new CLPEvent(4099, 6));
                        }

                        if (protocol.readBoolean(4099, 15)) {
                            listener.machineStopped(new CLPEvent(4099, 15));
                        } else {
                            listener.machineInMotion(new CLPEvent(4099, 15));
                        }

                        if (protocol.readBoolean(4100, 3)) {
                            listener.resetFailed(new CLPEvent(4100, 3));
                        } else {
                            listener.resetFailedOff(new CLPEvent(4100, 3));
                        }

                        if (protocol.readBoolean(4099, 14)) {
                            listener.machineOK(new CLPEvent(4099, 14));
                        } else {
                            listener.machineOFF(new CLPEvent(4099, 14));
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
    }
}

Perceba que agora não há mais aqueles for (CLPListener listener : listeners).
Mesmo que você adicione mais de um CLPListener, a classe CLPMonitor manipula apenas um objeto do tipo CLPListener.
O CLPEventMulticaster é quem liga um CLPListener com outro para atuar como uma lista, assim você não terá mais as java.util.ConcurrentModificationException.

Fiz estas alterações que você sugeriu e realmente não recebi mais a exceção, obrigada!

Quanto a ideia de remover um listener, em que casos eu deveria fazer isto?

Eu tenho uma instância única do CLPMonitor, à qual faço o addCLPListener em diversas telas do software, esse addCLPListener eu faço no setVisible() de cada tela, pois cada uma tem suas particularidades à executar em cada evento, entende? Gostaria de saber se esta é uma implementação correta ou se teria outra forma de fazer que seria mais indicada?

Quando você quiser, só pus o método para manter a ortogonalidade.
Não faz muito sentido você permitir adicionar algo à uma coleção e não permitir que remova.

Então, nesse caso, faz todo sentido você fazer o addCLPListener quando passar true para o setVisible e chamar o removeCLPListener quando passar false para o setVisible.

Eu até tentei isto, mas a princípio parece que ele remove “todos” e aí os eventos específicos não são mais disparados.

Outra coisa que notei é que, por exemplo, estou em uma tela e aí um dos eventos é disparado faz o que precisa, tranquilo, aí saio desta dela e entro em outra e o evento é disparado novamente e tals, mas aí pelo que parece ele ainda acessa o comportamento para aquele evento lá na outra tela que estava antes, o que será que pode ser?

Sim, porque você saiu da tela, mas o listener daquela tela continua registrado no CLPMonitor, por isso tem que remover ao sair da tela.

Não deveria, dá uma depurada no método remove do CLPEventMulticaster.

Você copiou a classe conforme eu postei?

Posta os seguintes códigos:

CLPEventMulticaster
CLPMonitor
1 ou 2 telas que adicionam um CLPListener

Fiz a depuração no método e pelo que notei ele sempre cai no:
if (atual == anterior || atual == null) {
return null;
}

Segue a classe CLPEventMulticaster:

public final class CLPEventMulticaster implements CLPListener {
    
    protected static CLPListener add(CLPListener atual, CLPListener proximo) {
        if (atual == null) {
            return proximo;
        }
        if (proximo == null) {
            return atual;
        }
        return new CLPEventMulticaster(atual, proximo);
    }

    protected static CLPListener remove(CLPListener atual, CLPListener anterior) {
        if (atual == anterior || atual == null) {
            return null;
        }
        if (atual instanceof CLPEventMulticaster) {
            return ((CLPEventMulticaster) atual).remove(anterior);
        }
        return atual;
    }

    private final CLPListener a;
    private final CLPListener b;

    private CLPEventMulticaster(CLPListener a, CLPListener b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public void generalEmergency(CLPEvent event) {
        a.generalEmergency(event);
        b.generalEmergency(event);
    }

    @Override
    public void generalEmergencyApproved(CLPEvent event) {
        a.generalEmergencyApproved(event);
        b.generalEmergencyApproved(event);
    }

    @Override
    public void securityCurtain(CLPEvent event) {
        a.securityCurtain(event);
        b.securityCurtain(event);
    }

    @Override
    public void securityCurtainApproved(CLPEvent event) {
        a.securityCurtainApproved(event);
        b.securityCurtainApproved(event);
    }

    @Override
    public void engineOverload(CLPEvent event) {
        a.engineOverload(event);
        b.engineOverload(event);
    }

    @Override
    public void failedMachine(CLPEvent event) {
        a.failedMachine(event);
        b.failedMachine(event);
    }

    @Override
    public void feedPositionOK(CLPEvent event) {
        a.feedPositionOK(event);
        b.feedPositionOK(event);
    }

    @Override
    public void tablePositioning(CLPEvent event) {
        a.tablePositioning(event);
        b.tablePositioning(event);
    }

    @Override
    public void positionTable(CLPEvent event) {
        a.positionTable(event);
        b.positionTable(event);
    }

    @Override
    public void machineStopped(CLPEvent event) {
        a.machineStopped(event);
        b.machineStopped(event);
    }

    @Override
    public void machineInMotion(CLPEvent event) {
        a.machineInMotion(event);
        b.machineInMotion(event);
    }

    @Override
    public void resetFailed(CLPEvent event) {
        a.resetFailed(event);
        b.resetFailed(event);
    }

    @Override
    public void resetFailedOff(CLPEvent event) {
        a.resetFailedOff(event);
        b.resetFailedOff(event);
    }

    @Override
    public void machineOK(CLPEvent event) {
        a.machineOK(event);
        b.machineOK(event);
    }

    @Override
    public void machineOFF(CLPEvent event) {
        a.machineOFF(event);
        b.machineOFF(event);
    }

    @Override
    public void machineReference(CLPEvent event) {
        a.machineReference(event);
        b.machineReference(event);
    }

    @Override
    public void machineReferenceOff(CLPEvent event) {
        a.machineReferenceOff(event);
        b.machineReferenceOff(event);
    }

    private CLPListener remove(CLPListener listener) {
        if (listener == a) {
            return b;
        }
        if (listener == b) {
            return a;
        }
        CLPListener primeiro = remove(a, listener);
        CLPListener segundo = remove(b, listener);
        if (primeiro == a && segundo == b) {
            return this;
        }
        return add(primeiro, segundo);
    }
}

Segue a classe CLPMonitor:

public class CLPMonitor {

    private Protocol protocol;
    private CLPListener listener;
    private static CLPMonitor eagerInstance = null;

    public static synchronized CLPMonitor getEagerInstance() {
        if (eagerInstance == null) {
            eagerInstance = new CLPMonitor();
        }
        return eagerInstance;
    }

    private CLPMonitor() {
        
    }

    public void start() {
        protocol = ActionMachineBuilder.getConnection();
        clpMonitor();
    }

    public void addCLPListener(CLPListener listener) {
        this.listener = CLPEventMulticaster.add(this.listener, listener);
    }

    public void removeCLPListener() {
        this.listener = CLPEventMulticaster.remove(this.listener, listener);
    }

    public void clpMonitor() {
        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                try {

                    if (ProtocolConstants.isdemonstrationmode) {
                        sleep(100);
                        return;
                    }

                    protocol.connect();

                    while (true) {
                        if (protocol.readBoolean(4099, 2)) {
                            listener.machineReference(new CLPEvent(4099, 2));
                        } else {
                            listener.machineReferenceOff(new CLPEvent(4099, 2));
                        }

                        if (protocol.readBoolean(4099, 9)) {
                            listener.generalEmergency(new CLPEvent(4099, 9));
                        } else {
                            listener.generalEmergencyApproved(new CLPEvent(4099, 9));
                        }

                        if (protocol.readBoolean(4140, 6)) {
                            listener.engineOverload(new CLPEvent(4140, 6));
                        }

                        if (protocol.readBoolean(4099, 8)) {
                            listener.failedMachine(new CLPEvent(4099, 8));
                        }

                        if (!protocol.readBoolean(4100, 2)) {
                            listener.tablePositioning(new CLPEvent(4100, 2));
                        }

                        if (protocol.readBoolean(4100, 7)) {
                            listener.positionTable(new CLPEvent(4100, 7));
                        }

                        if (protocol.readBoolean(4100, 4) && !protocol.readBoolean(4099, 9)) {
                            listener.securityCurtain(new CLPEvent(4100, 4));
                        } else {
                            listener.securityCurtainApproved(new CLPEvent(4100, 4));
                        }

                        if (protocol.readBoolean(4100, 3) && !protocol.readBoolean(4100, 4)) {
                            listener.resetFailed(new CLPEvent(4100, 3));
                        } else {
                            listener.resetFailedOff(new CLPEvent(4100, 3));
                        }

                        if (protocol.readBoolean(4099, 6)) {
                            listener.feedPositionOK(new CLPEvent(4099, 6));
                        }

                        if (protocol.readBoolean(4099, 15)) {
                            listener.machineStopped(new CLPEvent(4099, 15));
                        } else {
                            listener.machineInMotion(new CLPEvent(4099, 15));
                        }

                        if (protocol.readBoolean(4099, 14)) {
                            listener.machineOK(new CLPEvent(4099, 14));
                        } else {
                            listener.machineOFF(new CLPEvent(4099, 14));
                        }
                    }

                } catch (IOException e) {
                    // ignored
                    protocol.disconnect();
                }
            }
        });
        thread.start();
    }

Segue uma tela (AppMenuPane - tela principal do sistema):

public class AppMenuPane extends JPanel {

    private JPanel bottomMenu;
    private Protocol modbus;

    public AppMenuPane() {
        setLayout(new BorderLayout());
        
        modbus = ActionMachineBuilder.getConnection();
        modbus.disconnect();

        bottomMenu = new MenuPanePane(new FormLayout("0dlu,pref,0dlu,pref,0dlu,pref,0dlu,pref,0dlu,pref,0dlu,pref,0dlu,pref,0dlu,pref,0dlu,pref,0dlu", "0dlu,pref,0dlu"));
        add(bottomMenu, BorderLayout.SOUTH);
    
        // neste bottomMenu tem os botões que acessam as outras telas do sistema
    }

    @Override
    public void setVisible(boolean bln) {
        super.setVisible(bln);
        if (bln) {
            enabledButtons();

            try {
                modbus.connect();
            } catch (IOException ex) {
                //
            }

            CLPMonitor.getEagerInstance().addCLPListener(new CLPListener() {
                @Override
                public void generalEmergency(CLPEvent event) {
                    disableButtons();
                }

                @Override
                public void generalEmergencyApproved(CLPEvent event) {
                    enabledButtons();
                }

                @Override
                public void securityCurtain(CLPEvent event) {
                    disableButtons();
                }

                @Override
                public void securityCurtainApproved(CLPEvent event) {
                    try {
                        modbus.writeBoolean(4097, 9, false);
                        sleep(200);
                    } catch (IOException ex) {
                        //Logger.getLogger(AppMenuPane.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    enabledButtons();
                }

                @Override
                public void engineOverload(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void failedMachine(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void feedPositionOK(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void tablePositioning(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void positionTable(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void machineStopped(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void machineInMotion(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void resetFailed(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void resetFailedOff(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void machineOK(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void machineOFF(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void machineReference(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void machineReferenceOff(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }
            });
        } else {
            modbus.disconnect();
        }
    }

}

Segue outra tela (IOPane):

public class IOPane extends JPanel {

    private JButton backButton;
    private MenuPanePane bottomMenu;
    private Protocol modbus;

    public IOPane() {
        setLayout(new BorderLayout());
        
        modbus = ActionMachineBuilder.getConnection();
        modbus.disconnect();

       // aqui tem umas tabelas

        bottomMenu = new MenuPanePane(new FormLayout("0dlu,pref,0dlu,pref,0dlu,fill:pref:grow,0dlu,pref,0dlu", "0dlu,pref,0dlu"));
        add(bottomMenu, BorderLayout.SOUTH);

        backButton = ButtonUtility.makeButton();
        backButton.setText("Voltar");
        backButton.setPreferredSize(new Dimension(bw, bh));

        backButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                ModuleManager.getInstance().backToLastModule();
            }
        });
        bottomMenu.add(backButton, new CellConstraints(8, 2));
    }

    @Override
    public void setVisible(boolean bln) {
        super.setVisible(bln);

        if (bln) {

            try {
                modbus.connect();
            } catch (IOException ex) {
                //Logger.getLogger(IOPane.class.getName()).log(Level.SEVERE, null, ex);
            }

            CLPMonitor.getEagerInstance().addCLPListener(new CLPListener() {
                @Override
                public void generalEmergency(CLPEvent event) {
                    backButton.setEnabled(false);
                }

                @Override
                public void generalEmergencyApproved(CLPEvent event) {
                    backButton.setEnabled(true);
                }

                @Override
                public void securityCurtain(CLPEvent event) {
                    backButton.setEnabled(false);
                }

                @Override
                public void securityCurtainApproved(CLPEvent event) {
                    try {
                        modbus.writeBoolean(4097, 9, false);
                        sleep(200);
                    } catch (IOException ex) {
                        //Logger.getLogger(IOPane.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    backButton.setEnabled(true);
                }

                @Override
                public void engineOverload(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void failedMachine(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void feedPositionOK(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void tablePositioning(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void positionTable(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void machineStopped(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void machineInMotion(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void resetFailed(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void resetFailedOff(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void machineOK(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void machineOFF(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void machineReference(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }

                @Override
                public void machineReferenceOff(CLPEvent event) {
                    //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }
            });
        } else {
            modbus.disconnect();
        }
    }
}

Bom, no geral as telas seguem sempre essa mesma estrutura, algumas delas ao clicar no botão de voltar irão retornar sempre para a tela principal (AppMenuPane), outras delas irão voltar para a tela aberta anteriormente (sistema de histórico de telas).

Outra coisa, tenho uma “tela” que nada verdade é um um painel de menu, que fica visível durante todo o tempo, nele eu também tenho um addCLPListener, será que isso não pode ser um problema?

É que na classe CLPMonitor você implementou errado o método removeCLPListener, veja:

public void removeCLPListener() { // está faltando o parâmetro listener
    this.listener = CLPEventMulticaster.remove(this.listener, listener); // você está removendo o this.listener
}

O correto é assim:

public void removeCLPListener(CLPListener listenerParaRemover) {
    this.listener = CLPEventMulticaster.remove(this.listener, listenerParaRemover);
}

Eu vi que as implementações dos seus CLPListeners tem muitos métodos vazios, faz sentido pois em cada tela você só quer tratar alguns eventos específicos, mas fica muito feio você toda vez implementar todos os métodos vazios.
O ideal nesse caso, é ter uma classe abstrata que implementa o CLPListener sem fazer nada, aí ao invés de implementar diretamente o CLPListener, você estende essa classe e só sobrescreve os métodos dos eventos do seu interesse.

Vamos criar a classe CLPAdapter, com métodos que não fazem nada:

public abstract class CLPAdapter implements CLPListener {

    @Override
    public void machineReference(CLPEvent clpEvent) {}

    @Override
    public void machineReferenceOff(CLPEvent clpEvent) {}

    @Override
    public void generalEmergency(CLPEvent clpEvent) {}

    @Override
    public void generalEmergencyLiberate(CLPEvent clpEvent) {}

    @Override
    public void engineOverload(CLPEvent clpEvent) {}

    @Override
    public void failedMachine(CLPEvent clpEvent) {}

    @Override
    public void tablePositioning(CLPEvent clpEvent) {}

    @Override
    public void positionTable(CLPEvent clpEvent) {}

    @Override
    public void securityCurtain(CLPEvent clpEvent) {}

    @Override
    public void securityCurtainLiberate(CLPEvent clpEvent) {}

    @Override
    public void feedPositionOK(CLPEvent clpEvent) {}

    @Override
    public void machineStopped(CLPEvent clpEvent) {}

    @Override
    public void machineInMotion(CLPEvent clpEvent) {}

    @Override
    public void resetFailed(CLPEvent clpEvent) {}

    @Override
    public void resetFailedOff(CLPEvent clpEvent) {}

    @Override
    public void machineOK(CLPEvent clpEvent) {}

    @Override
    public void machineOFF(CLPEvent clpEvent) {}

}

Agora veja como suas telas ficam com um código mais limpo:

Tela AppMenuPane:

public class AppMenuPane extends JPanel {

    // com o uso do CLPAdapter, basta sobrescrever apenas os métodos do eventos de interesse desta tela
    private final CLPListener listener = new CLPAdapter() {

        @Override
        public void generalEmergency(CLPEvent event) {
            disableButtons();
        }

        @Override
        public void generalEmergencyApproved(CLPEvent event) {
            enabledButtons();
        }

        @Override
        public void securityCurtain(CLPEvent event) {
            disableButtons();
        }

        @Override
        public void securityCurtainApproved(CLPEvent event) {
            try {
                modbus.writeBoolean(4097, 9, false);
                sleep(200);
            } catch (IOException ex) {
                // Logger.getLogger(AppMenuPane.class.getName()).log(Level.SEVERE, null, ex);
            }
            enabledButtons();
        }
    };

    private JPanel bottomMenu;
    private Protocol modbus;

    public AppMenuPane() {
        setLayout(new BorderLayout());

        modbus = ActionMachineBuilder.getConnection();
        modbus.disconnect();

        bottomMenu = new MenuPanePane(new FormLayout("0dlu,pref,0dlu,pref,0dlu,pref,0dlu,pref,0dlu,pref,0dlu,pref,0dlu,pref,0dlu,pref,0dlu,pref,0dlu","0dlu,pref,0dlu"));
        add(bottomMenu, BorderLayout.SOUTH);

        // neste bottomMenu tem os botões que acessam as outras telas do sistema
    }

    @Override
    public void setVisible(boolean visible) {
        super.setVisible(visible);
        try {
            CLPMonitor clpMonitor = CLPMonitor.getEagerInstance();
            if (visible) {
                enabledButtons();
                modbus.connect();
                clpMonitor.addCLPListener(listener);
            } else {
                modbus.disconnect();
                clpMonitor.removeCLPListener(listener);
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

}

Tela IOPane:

public class IOPane extends JPanel {

    // com o uso do CLPAdapter, basta sobrescrever apenas os métodos do eventos de interesse desta tela
    private final CLPListener listener = new CLPAdapter() {
        @Override
        public void generalEmergency(CLPEvent event) {
            backButton.setEnabled(false);
        }

        @Override
        public void generalEmergencyApproved(CLPEvent event) {
            backButton.setEnabled(true);
        }

        @Override
        public void securityCurtain(CLPEvent event) {
            backButton.setEnabled(false);
        }

        @Override
        public void securityCurtainApproved(CLPEvent event) {
            try {
                modbus.writeBoolean(4097, 9, false);
                sleep(200);
            } catch (IOException ex) {
                // Logger.getLogger(IOPane.class.getName()).log(Level.SEVERE, null, ex);
            }
            backButton.setEnabled(true);
        }
    };

    private JButton backButton;
    private MenuPanePane bottomMenu;
    private Protocol modbus;

    public IOPane() {
        setLayout(new BorderLayout());

        modbus = ActionMachineBuilder.getConnection();
        modbus.disconnect();

        // aqui tem umas tabelas

        bottomMenu = new MenuPanePane(new FormLayout("0dlu,pref,0dlu,pref,0dlu,fill:pref:grow,0dlu,pref,0dlu", "0dlu,pref,0dlu"));
        add(bottomMenu, BorderLayout.SOUTH);

        backButton = ButtonUtility.makeButton();
        backButton.setText("Voltar");
        backButton.setPreferredSize(new Dimension(bw, bh));

        backButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                ModuleManager.getInstance().backToLastModule();
            }
        });
        bottomMenu.add(backButton, new CellConstraints(8, 2));
    }

    @Override
    public void setVisible(boolean visible) {
        super.setVisible(visible);
        try {
            CLPMonitor clpMonitor = CLPMonitor.getEagerInstance();
            if (visible) {
                modbus.connect();
                clpMonitor.addCLPListener(listener);
            } else {
                modbus.disconnect();
                clpMonitor.removeCLPListener(listener);
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

Olá staroski,

Muito obrigada, implementei de acordo com suas orientações e está funcionando perfeitamente bem. :wink:

Agora estou com um outro “probleminha”, talvez até fuja do que vínhamos falando, mas enfim, em um deste eventos disparados eu abro um JDialog e com a liberação deste eu abro outro JDialog que ficará aguardando se o usuário quer prosseguir ou não, mas está acontecendo que quando abre a primeira vez (somente na primeira) ele não mostra os JLabel somente os JButton, aí depois nas outras vezes mostra certo, sabe me dizer o que seria? E olha que eu tenho mais dois JDialogs que também abro no disparar de algum destes eventos, inclusive o que abre antes deste que dá o problema, mas em nenhum acontece isto …

Cria um novo tópico, explicando esse novo problema e posta os fontes.
:slight_smile:

Obrigada staroski. :call_me_hand:

1 curtida