JMS Fila para JTable Atualização [Agora recebendo exceção após as alterações]

StackOverflow https://stackoverflow.com/questions/1624679

  •  06-07-2019
  •  | 
  •  

Pergunta

Eu estou escrevendo meu próprio navegador JMS e eu sou golpeado na atualização JTable de mensagens de servidores JMS. Eu tentei AbstractTableModel TableModelListener para fazer atualização JTable quando os dados adicionados em LinkedList. Este abaixo obras Logis, mas o seu tempo real não atualizar, meios eu gostaria de exibir cada linha adicionada para JTable imediatamente quando seu adicionada a partir QueueBrowser para LinkedList.

Eu atualizei o código de acordo com as sugestões abaixo.

Estou fazendo algo errado? Alguém pode me ajudar?

QueueBrowser qb = session.createBrowser(q);
MsgTable mt = (MsgTable) queueTable.getModel();
mt.load(qb.getEnumeration(),mt);
qb.close();




 class MsgTable extends AbstractTableModel implements TableModelListener{


      final String[] columnNames = { "#", "Timestamp", "Type", "Mode",
        "Priority" };

      public void setRowSize(){

      }
      LinkedList queueList = new LinkedList();

      public int getRowCount() { if (queueList == null) { return 0; } else { return queueList.size();}}
      public int getColumnCount() { return columnNames.length;}
      public String getColumnName(int column) {return columnNames[column];}

      public Object getValueAt(int row, int column) {
       if(queueList == null){
        return null;
       }
                        Message m = (Message) queueList.get(row);
                        ...  
      }

      void load(Enumeration e,MsgTable mt) {
                         mt.addTableModelListener(this);
        while(e.hasMoreElements()){
         queueList.add(e.nextElement());

        }
                      fireTableDataChanged();   
      }

      Message getMessageAtRow(int row) {
       if (queueList == null)
        return null;
       return ((Message) queueList.get(row));
      }

                @Override
  public void tableChanged(TableModelEvent arg0) {
   // TODO Auto-generated method stub
   fireTableDataChanged();
  }

}

e recebendo essa exceção.

Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError  at javax.swing.table.AbstractTableModel.fireTableRowsInserted(Unknown Source)

É errado?

Foi útil?

Solução

Para meu conhecimento, o seu JTable deve atualizar automaticamente quando uma alteração no TableModel acontece. Confira o tutorial sol na trabalhar com tabelas especialmente a seção sobre de escuta para alterações de dados , isso pode ajudar. Dito isto, eu tenho um par de observações:

  • Eu realmente não entendo o método getValueAt(int row, int col). você não deve ter a linha-th mensagem eo col-th atributo da mensagem?

  • Eu adicionaria um addRow(...) e addRows(...) a implementação MsgTable de TableModel para atualizar o modelo interno e acionar o evento apropriado.

  • Você não precisa implementar TableModelListener (eu não posso ver qualquer chamada para addTableModelListener(...) de qualquer maneira)

(EDIT:. O OP actualiza a sua pergunta com novo código então eu estou atualizando a minha resposta em conformidade abaixo)

Você modificou a assinatura load(...) e do corpo para adicionar uma chamada para addTableModelListener(...) e eu acho que ambas as modificações não estão corretas.

Sobre o addTableModelListener (... ) , a documentação diz:

Adiciona um ouvinte para a lista que é notificado cada vez que uma mudança para o modelo de dados ocorre.

E sobre os vários métodos fireFooXxx(...):

notifica todos os ouvintes que [a mudaram ocorreu]

Assim, com a seguinte implementação de um TableModelListener:

@Override
public void tableChanged(TableModelEvent arg0) {
    // TODO Auto-generated method stub
    fireTableDataChanged();
} 

Você vai acabar fazendo chamadas recursivas infinitas (o ouvinte é notificado por uma mudança e disparar um evento que irá notificá-lo de novo etc), daí o java.lang.StackOverflowError .

Na verdade, eu ainda acho que você não precisa de um TableModelListener (e do jeito que você está registrando não é correto IMO, consulte Ouvir para alterações de dados no tutorial Sun). Eu, portanto, remover a implements TableModelListener e bastante implementar o método load(...) assim:

void load(Enumeration e) {
    while(e.hasMoreElements()) {
        queueList.add(e.nextElement());
    }
    fireTableDataChanged();   
}

Outras dicas

pontos casal um para adicionar à consideração:

  • seu método load(Enumeration e) não precisa jogar um JMSException, como você está apenas interagindo sobre um Enumeration.
  • você deve garantir que o seu disparo de eventos é feito dentro da EDT. Isso pode ser tão simples como embalar sua chamada para load em um executável e soltando-a SwingUtilities.invokeLater():

    MsgTable mt = (MsgTable) queueTable.getModel();
    final Enumeration e = qb.getEnumeration();
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            mt.load(e);
        }
    });
    

uma maneira de-se o desempenho seria apenas para chamar fireTableDataChanged () no final do método de carga (), em oposição a após cada linha é carregado.

que deve ajudar.

ou seja:

void load(Enumeration e) throws JMSException {
                 while(e.hasMoreElements()){
                         queueList.add(e.nextElement());
                         fireTableDataChanged();
                 }                      
        }

para

void load(Enumeration e) throws JMSException {
                 boolean dataAdded = false;
                 while(e.hasMoreElements()){
                         queueList.add(e.nextElement());
                         dataAdded = true;
                     }
                 fireTableDataChanged();

        }

Bem, o bom design é criar um método addRow (...) que recebe uma linha de dados e atualiza o armazenamento interno de seu TableModel. Este método deveria então invocar o método fileTableRowsInserted (). Seu método getValueAt () também não faz sentido. De acordo com o modelo que você tem 5 colunas de dados, mas você nunca verificar a variável de coluna para retornar o objeto coluna adequada.

Dê uma olhada no código fonte do DefaultTableModel para ver como um insertRow () e getValueAt () método pode ser codificada.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top