【问题标题】:JMS Queue to JTable Update [Now getting exception after changes]JMS 队列到 JTable 更新 [现在更改后出现异常]
【发布时间】:2009-10-26 13:07:58
【问题描述】:

我正在编写自己的 JMS 浏览器,我对来自 JMS 服务器的消息的 JTable 更新感到震惊。 我已经尝试AbstractTableModelTableModelListener 在将数据添加到 LinkedList 时使 Jtable 刷新。 下面的 logis 有效,但它不是实时更新,这意味着我想显示添加到的每一行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)

错了吗?

【问题讨论】:

  • 除了一些明显的性能问题,理论上代码看起来还可以。你的实际问题是什么?
  • @jambjo ,它工作正常,但是 Jtable 在列表获取所有数据时显示数据,而不是在添加到 LinkiedList 时显示实时刷新

标签: java swing jtable


【解决方案1】:

据我所知,当TableModel 发生更改时,您的JTable 应该会自动更新。查看working with tables 上的太阳教程,特别是listening for data changes 上的部分,这可能会有所帮助。也就是说,我有几点意见:

  • 我真的不明白getValueAt(int row, int col) 方法。你不应该得到第行消息和消息的第列属性吗?

  • 我会在 TableModel 的 MsgTable 实现中添加 addRow(...) 和 addRows(...),以更新内部模型并触发适当的事件。

  • 你不需要实现TableModelListener(反正我看不到对addTableModelListener(...)的任何调用)

(编辑:OP 已经用新代码更新了他的问题,所以我在下面相应地更新了我的答案。)

您已修改 load(...) 签名和正文以添加对 addTableModelListener(...) 的调用,我认为这两个修改都不正确。

关于addTableModelListener(...),文档说:

向列表中添加一个侦听器,每次数据模型发生更改时都会收到通知。

关于各种fireFooXxx(...) 方法:

通知所有侦听器[发生了更改]

因此使用TableModelListener 的以下实现:

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

您最终会进行无限递归调用(侦听器会收到更改通知并触发将再次通知他的事件等),因此java.lang.StackOverflowError。

实际上,我仍然认为您不需要TableModelListener(并且您注册它的方式不正确IMO,请参阅Sun 教程中的Listening for Data Changes)。因此,我将删除implements TableModelListener,而是像这样实现load(...) 方法:

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

【讨论】:

  • 谢谢帕斯卡。这是有道理的,让我检查一下然后回来。
【解决方案2】:

有几点需要考虑:

  • 您的load(Enumeration e) 方法不需要抛出JMSException,因为您只是在迭代Enumeration。
  • 您应该确保在 EDT 内触发事件。这可以简单到将您对 load 的调用包装在一个可运行文件中并将其放入 SwingUtilities.invokeLater() 中:

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

【讨论】:

    【解决方案3】:

    提高性能的一种方法是仅在 load() 方法结束时调用 fireTableDataChanged(),而不是在加载每一行之后。

    这应该会有所帮助。

    即:

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

    【讨论】:

    • 我同意了,但我想在新数据添加到列表的那一刻更新Jtable。
    【解决方案4】:

    好吧,正确的设计是创建一个 addRow(...) 方法来接收一行数据并更新 TableModel 的内部存储。然后,此方法应调用 fileTableRowsInserted() 方法。您的 getValueAt() 方法也没有任何意义。根据您的模型,您有 5 列数据,但您从不检查列变量以返回正确的列对象。

    查看 DefaultTableModel 的源代码,了解如何编写 insertRow() 和 getValueAt() 方法。

    【讨论】:

      猜你喜欢
      • 2016-09-18
      • 2017-02-04
      • 1970-01-01
      • 2012-08-27
      • 1970-01-01
      • 2011-08-21
      • 1970-01-01
      • 2020-05-19
      • 1970-01-01
      相关资源
      最近更新 更多