Очередь JMS для обновления JTable [Теперь получаем исключение после изменений]

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

  •  06-07-2019
  •  | 
  •  

Вопрос

Я пишу свой собственный браузер JMS, и я поражен обновлением JTable сообщений с серверов JMS. Я пытался AbstractTableModel TableModelListener чтобы Jtable обновлялся при добавлении данных в LinkedList. Приведенный ниже логис работает, но он не обновляется в режиме реального времени, что означает, что я хотел бы отображать каждую строку, добавленную в Jtable, сразу после ее добавления из QueueBrowser в LinkedList.

Я обновил код в соответствии с приведенными ниже предложениями.

Я делаю что-то не так?кто - нибудь может мне помочь ?

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();
  }

}

и получаю это исключение.

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

Это неправильно ?

Это было полезно?

Решение

Насколько мне известно, ваш JTable должен обновляться автоматически при изменении TableModel случается.Ознакомьтесь с руководством sun по работа с таблицами и особенно раздел, посвященный прослушивание изменений данных, это может помочь.Тем не менее, у меня есть пара замечаний:

  • Я действительно не понимаю getValueAt(int row, int col) способ.Разве вы не должны получить сообщение row-th и атрибут col-th сообщения?

  • Я бы добавил addRow(...) и addRows(...) Для MsgTable реализация TableModel для обновления внутренней модели и запуска соответствующего события.

  • Вам не нужно внедрять TableModelListener (Я не вижу никакого призыва к addTableModelListener(...) в любом случае)

(РЕДАКТИРОВАТЬ:OP обновил свой вопрос новым кодом, поэтому я соответствующим образом обновляю свой ответ ниже.)

Вы изменили load(...) подпись и текст для добавления вызова addTableModelListener(...) и я думаю, что обе модификации неверны.

О том, что addTableModelListener(...), в документации говорится:

Добавляет прослушиватель в список, который получает уведомление каждый раз, когда происходит изменение модели данных.

И о различных fireFooXxx(...) методы:

Уведомляет всех слушателей о том, что [произошло изменение]

Итак, при следующей реализации a TableModelListener:

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

В конечном итоге вы будете выполнять бесконечные рекурсивные вызовы (слушатель получает уведомление об изменении и запускает событие, которое уведомит его снова и т.д.), Следовательно, java.lang.StackOverflowError.

На самом деле, я все еще думаю, что тебе не нужен TableModelListener (и способ, которым вы это регистрируете, неверен, IMO, см. Прослушивание изменений данных в учебном пособии Sun).Таким образом, я бы удалил implements TableModelListener и скорее реализуйте load(...) метод, подобный этому:

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

Другие советы

Хочу добавить пару моментов для рассмотрения:

  • твой load(Enumeration e) методу не нужно выбрасывать JMSException, поскольку вы просто повторяете Enumeration.
  • вы должны убедиться, что запуск событий выполняется в рамках EDT.Это может быть так же просто, как обернуть ваш вызов в load в runnable и помещаем его в SwingUtilities.invokeLater() :

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

одним из способов повышения производительности было бы вызывать fireTableDataChanged() только в конце метода load(), в отличие от после загрузки каждой строки.

это должно помочь.

т. е.:

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

Для

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

        }

Что ж, правильный дизайн - создать метод addRow (...), который получает строку данных и обновляет внутреннее хранилище вашей TableModel. Этот метод должен затем вызвать метод fileTableRowsInserted (). Ваш метод getValueAt () также не имеет смысла. Согласно вашей модели у вас есть 5 столбцов данных, но вы никогда не проверяете переменную столбца, чтобы получить правильный объект столбца.

Взгляните на исходный код DefaultTableModel, чтобы увидеть, как могут быть закодированы методы insertRow () и getValueAt ().

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top