2012-04-26 26 views
1

TableModelListener定义监听 TableModel中的更改的对象的接口。当DefaultTableModel已更改时,JTable上的setModel

TableModelListener

如何应用此JTable的,所以它会听在一个DefaultTableModel变化?此外,setModel被调用后,是否应该不内置该功能?为什么你不希望JTable能够反映模型的变化?

News中defaultTableModel的引用指向MessagesController中的同一实例(这是否正确?),那么为什么我必须在JTable上显式调用setModel(如果底层对象已更新?

JTable更新自身的更好方法是什么?也许tableChanged

我不明白,如果News中的引用和MessagesController中的引用指向不同的对象,具有相同的值,为什么需要调用setModel()。毕竟,News.defaultTableModel现在已经更新。为什么重新调用setModel()?

package net.bounceme.dur.nntp; 

import java.awt.Dimension; 
import java.awt.GridLayout; 
import java.awt.Toolkit; 
import java.util.logging.Logger; 
import javax.swing.*; 
import javax.swing.event.ListSelectionEvent; 
import javax.swing.event.ListSelectionListener; 
import javax.swing.table.DefaultTableModel; 

public class News { 

    private static final Logger LOG = Logger.getLogger(News.class.getName()); 
    static JFrame frame = new JFrame(); 
    static JTextPane text = new JTextPane(); 
    static JSlider slider = new JSlider(); 
    static MessagesController messagesController = new MessagesController(); 
    static DefaultTableModel defaultTableModel = new DefaultTableModel(); 
    static JTable table = new JTable(); 

    private static void createAndShowGUI() { 
     defaultTableModel = messagesController.getDefaultTableModel(); 
     table.setModel(defaultTableModel); 
     table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
     table.getSelectionModel().addListSelectionListener(new ListSelectionListener() { 

      public void valueChanged(ListSelectionEvent evt) { 
       java.awt.EventQueue.invokeLater(new Runnable() { 

        public void run() { 
         int row = table.convertRowIndexToModel(table.getSelectedRow()); 
         row = Math.abs(row); //how can this be negative? 
         LOG.fine("row " + row); 
         MessageBean messageBean = messagesController.getMessageBean(row); 
         text.setText(messageBean.getContent()); 
         text.setContentType("text/html"); 
        } 
       }); 
      } 
     }); 

     slider.setMinimum(1); 
     slider.setMaximum(messagesController.getMax()); 
     slider.setValue(messagesController.getMax()); 
     slider.addChangeListener(new javax.swing.event.ChangeListener() { 

      public void stateChanged(javax.swing.event.ChangeEvent evt) { 
       java.awt.EventQueue.invokeLater(new Runnable() { 

        public void run() { 
         int index = slider.getValue(); 
         LOG.fine("slider " + index); 
         messagesController.setIndex(index); 
         defaultTableModel = messagesController.getDefaultTableModel(); 
         table.setModel(defaultTableModel); 
         table.getSelectionModel().setSelectionInterval(1, 1); 
        } 
       }); 
      } 
     }); 
     table.getSelectionModel().setSelectionInterval(1, 1); 
     JPanel panel = new JPanel(); 
     panel.setLayout(new GridLayout(3, 1)); 
     panel.add(table); 
     panel.add(text); 
     panel.add(slider); 
     frame.add(panel); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
     frame.pack(); 
     frame.setVisible(true); 
     frame.setSize(screenSize); 
    } 

    public static void main(String args[]) { 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 

      public void run() { 
       createAndShowGUI(); 
      } 
     }); 
    } 
} 

也许我误会pass-by-value,虽然我已阅读这些条款都取决于上下文不同的含义。

回答

3

为什么我必须显式调用setModel()JTable,如果底层对象已更新?

您不应该。

JTable自我更新的更好方法是什么?

更新模型TableModel应激发所需的事件以通知视图JTable自行更新。 DefaultTableModel为您做到这一点; AbstractTableModel为您的模型调用方法提供了方便的fireXxx()方法。后者有一个例子here。另请参阅​​。

News中创建一个新的空DefaultTableModel似乎是虚假的,因为(看不见的)MessagesController模型会立即替换它。

目前还不清楚为什么在ListSelectionListenerChangeListener中使用invokeLater()。这些方法应该已经在event dispatch thread上运行。如果没有,您需要同步访问任何共享数据。

+0

我一定是做错了。在新闻中,我有一个Jtable,JFrame等 - 视图。在MessagesController,POJO bean中,我填充DefaultTableModel。我不知道我做错了什么,除了它没有像预期的那样工作以及如上所述。我应该编辑问题以反映新代码,还是仅仅关闭问题? – Thufir 2012-04-29 17:17:15

+0

越接近[sscce](http://sscce.org/)越好。您有可能在网络运营中阻止EDT?另请参阅此SwingWorker [示例](https://sites.google.com/site/drjohnbmatthews/randomdata)。 – trashgod 2012-04-29 17:32:13

+0

我不这么认为。稍后我会回过头来看,也许有些时候会更好地理解答案。这不是EDT问题,我很确定,而且都在本地主机上。谢谢! – Thufir 2012-05-03 12:21:31

3

1)row = Math.abs(row); //how can this be negative?

如果不存在任何选择的行然后代码线

int row = table.convertRowIndexToModel(table.getSelectedRow()); 

返回-1值,更好的是什么

2)那里没有理由之前测试if(table.getSelectedRow() > -1)替换TableModel和DefaultTableModel,JTable都可以返回它的TableModel,JTable#getModel

3)根据上下文不知道,但也许你看看JTable Sorting and Filtering

+0

感谢您澄清-1问题,我猜-1就像“假”一样。虽然我不明白你的主要答案,但我会稍后再回来阅读。我在我的问题的末尾添加了一个链接,这比我们提到的要多一些。我可能不得不大量编辑我的问题。 – Thufir 2012-04-26 11:09:48

+0

纠正所有计数;更多[这里](http://stackoverflow.com/a/10334049/230513)。 – trashgod 2012-04-26 13:06:23