JTable数据实时更新
Jtable中一般使用 AbstractTableModel 和DefaultTableModel两个数据模型来管理需要显示的数据。自定义数据模型只需继承AbstractTableModel 。此时需要实现三个方法:
public int getColumnCount( ) //设定行数
public int getRowCount( )       //设定列数
public Object getValueAt(int row, int col)//设定指定位置的值
我为了使table动态更新数据,想尽了各种办法,查了各种资料,比较统一 的方法有两种:
1、更新数据模型,然后调用JTable的validate( ) 和updateUI( )方法。
2、更新数据模型,((AbstractTableModel)table.getModel()).fireTableDataChanged();
初始版本,在外部文件中修改数据,表格不能更新:
- import java.awt.Dimension;
 - import java.io.File;
 - import java.io.FileReader;
 - import java.util.ArrayList;
 - import java.util.List;
 - import javax.swing.JFrame;
 - import javax.swing.JPanel;
 - import javax.swing.JScrollPane;
 - import javax.swing.JTable;
 - import javax.swing.table.AbstractTableModel;
 - import javax.swing.table.TableModel;
 - public class Test extends JPanel implements Runnable {
 - TableModel dataModel;
 - JScrollPane scrollpane;
 - JTable table;
 - public Test() {
 - dataModel = getTableModel();
 - table = new JTable(dataModel);
 - scrollpane = new JScrollPane(table);
 - this.add(scrollpane);
 - }
 - //读取外部文件,每一行当做一条字符串存入List中
 - public List<String> getData() {
 - FileReader fr;
 - File file = new File(
 - "E:/my.txt");
 - int b;
 - StringBuffer sb = new StringBuffer();
 - List<String> s = new ArrayList<String>();
 - try {
 - fr = new FileReader(file);
 - while ((b = fr.read()) != -1) {
 - if (b != '\r') {
 - sb.append((char) b);
 - }
 - if (b == '\n') {
 - s.add(sb.toString());
 - sb = new StringBuffer();
 - }
 - }
 - fr.close();
 - } catch (Exception e) {
 - e.printStackTrace();
 - }
 - return s;
 - }
 - //使用public List<String> getData() 方法得到的List构建数据模型
 - //此处使用的外部文件中,每一行的字符串用空格分成四个部分
 - //例如,其中一行为:2013-03-18 11:50:55 传感器1 报警,对应表格的一行
 - public AbstractTableModel getTableModel() {
 - return new AbstractTableModel() {
 - List<String> list=getData();
 - public int getColumnCount() {
 - return 4;
 - }
 - public int getRowCount() {
 - return list.size();
 - }
 - public Object getValueAt(int row, int col) {
 - switch (col) {
 - case (0): {
 - return row + 1;
 - }
 - case (1): {
 - return list.get(row).split(" ", 0)[0];
 - }
 - case (2): {
 - return list.get(row).split(" ", 0)[1];
 - }
 - default:
 - return list.get(row).split(" ", 0)[2];
 - }
 - }
 - };
 - }
 - public void run() {
 - while (true) {
 - //每隔1秒钟更新JTable
 - table.validate();
 - <span style="color:#ff0000;">table.updateUI();
 - </span> try {
 - Thread.sleep(1000);
 - } catch (InterruptedException e) {
 - e.printStackTrace();
 - }
 - }
 - }
 - public static void main(String[] g) {
 - JFrame frame = new JFrame();
 - Test t = new Test();
 - frame.add(t);
 - frame.setSize(new Dimension(400, 400));
 - frame.setVisible(true);
 - new Thread(t).start();
 - }
 - }
 
 修改版本,实时更新:
- import java.awt.Dimension;
 - import java.io.File;
 - import java.io.FileReader;
 - import java.util.ArrayList;
 - import java.util.List;
 - import javax.swing.JFrame;
 - import javax.swing.JPanel;
 - import javax.swing.JScrollPane;
 - import javax.swing.JTable;
 - import javax.swing.table.AbstractTableModel;
 - import javax.swing.table.TableModel;
 - public class Test extends JPanel implements Runnable {
 - TableModel dataModel;
 - JScrollPane scrollpane;
 - JTable table;
 - public Test() {
 - dataModel = getTableModel();
 - table = new JTable(dataModel);
 - scrollpane = new JScrollPane(table);
 - this.add(scrollpane);
 - }
 - //读取外部文件,每一行当做一条字符串存入List中
 - public List<String> getData() {
 - FileReader fr;
 - File file = new File(
 - "E:/my.txt");
 - int b;
 - StringBuffer sb = new StringBuffer();
 - List<String> s = new ArrayList<String>();
 - try {
 - fr = new FileReader(file);
 - while ((b = fr.read()) != -1) {
 - if (b != '\r') {
 - sb.append((char) b);
 - }
 - if (b == '\n') {
 - s.add(sb.toString());
 - sb = new StringBuffer();
 - }
 - }
 - fr.close();
 - } catch (Exception e) {
 - e.printStackTrace();
 - }
 - return s;
 - }
 - //使用public List<String> getData() 方法得到的List构建数据模型
 - //此处使用的外部文件中,每一行的字符串用空格分成四个部分
 - //例如,其中一行为:2013-03-18 11:50:55 传感器1 报警,对应表格的一行
 - public AbstractTableModel getTableModel() {
 - return new AbstractTableModel() {
 - public int getColumnCount() {
 - return 4;
 - }
 - public int getRowCount() {
 - return getData().size();
 - }
 - public Object getValueAt(int row, int col) {
 - switch (col) {
 - case (0): {
 - return row + 1;
 - }
 - case (1): {
 - return getData().get(row).split(" ", 0)[0];
 - }
 - case (2): {
 - return getData().get(row).split(" ", 0)[1];
 - }
 - default:
 - return getData().get(row).split(" ", 0)[2];
 - }
 - }
 - };
 - }
 - public void run() {
 - while (true) {
 - //每隔1秒钟更新JTable
 - table.validate();
 - table.updateUI();
 - try {
 - Thread.sleep(1000);
 - } catch (InterruptedException e) {
 - e.printStackTrace();
 - }
 - }
 - }
 - public static void main(String[] g) {
 - JFrame frame = new JFrame();
 - Test t = new Test();
 - frame.add(t);
 - frame.setSize(new Dimension(400, 400));
 - frame.setVisible(true);
 - new Thread(t).start();
 - }
 - }
 
区别是public AbstractTableModel getTableModel()方法不同
仔细研究后发现,JTable在调用validate( ) 和updateUI( )方法时,通过 public Object getValueAt(int row, int col)方法去取得指定位置的值。
前一种情况下虽然调用了该方法,但是外部文件中数据变化并未反映在List<String> list中,list只在实例化AbstractTableModel时得到值,
以后并未更新。
而后一种,表格的值是通过调用getData( )方法取得,每一次都是在外部文件中读取。
因此,更新数据模型就能使JTable更新,前提是数据模型的值确实更新了。
前面的实现中用了线程来动态更新,swing中更好的办法是用户Timer:
- import java.awt.Dimension;
 - import java.awt.event.ActionEvent;
 - import java.awt.event.ActionListener;
 - import java.io.File;
 - import java.io.FileReader;
 - import java.util.ArrayList;
 - import java.util.List;
 - import javax.swing.JFrame;
 - import javax.swing.JPanel;
 - import javax.swing.JScrollPane;
 - import javax.swing.JTable;
 - import javax.swing.Timer;
 - import javax.swing.table.AbstractTableModel;
 - import javax.swing.table.TableModel;
 - public class Test extends JPanel {
 - TableModel dataModel;
 - JScrollPane scrollpane;
 - JTable table;
 - Timer timer;
 - public Test() {
 - dataModel = getTableModel();
 - table = new JTable(dataModel);
 - scrollpane = new JScrollPane(table);
 - timer=new Timer(1000,new ActionListener() {
 - public void actionPerformed(ActionEvent evt) {
 - table.validate();
 - table.updateUI();
 - }
 - });
 - timer.start();
 - this.add(scrollpane);
 - }
 - //读取外部文件,每一行当做一条字符串存入List中
 - public List<String> getData() {
 - FileReader fr;
 - File file = new File(
 - "E:/my.txt");
 - int b;
 - StringBuffer sb = new StringBuffer();
 - List<String> s = new ArrayList<String>();
 - try {
 - fr = new FileReader(file);
 - while ((b = fr.read()) != -1) {
 - if (b != '\r') {
 - sb.append((char) b);
 - }
 - if (b == '\n') {
 - s.add(sb.toString());
 - sb = new StringBuffer();
 - }
 - }
 - fr.close();
 - } catch (Exception e) {
 - e.printStackTrace();
 - }
 - return s;
 - }
 - //使用public List<String> getData() 方法得到的List构建数据模型
 - //此处使用的外部文件中,每一行的字符串用空格分成四个部分
 - //例如,其中一行为:2013-03-18 11:50:55 传感器1 报警,对应表格的一行
 - public AbstractTableModel getTableModel() {
 - return new AbstractTableModel() {
 - public int getColumnCount() {
 - return 4;
 - }
 - public int getRowCount() {
 - return getData().size();
 - }
 - public Object getValueAt(int row, int col) {
 - switch (col) {
 - case (0): {
 - return row + 1;
 - }
 - case (1): {
 - return getData().get(row).split(" ", 0)[0];
 - }
 - case (2): {
 - return getData().get(row).split(" ", 0)[1];
 - }
 - default:
 - return getData().get(row).split(" ", 0)[2];
 - }
 - }
 - };
 - }
 - public static void main(String[] g) {
 - JFrame frame = new JFrame();
 - Test t = new Test();
 - frame.add(t);
 - frame.setSize(new Dimension(400, 400));
 - frame.setVisible(true);
 - //t.timer.start();
 - }
 - }
 
效果一样 。
                    
                
                
            
        
浙公网安备 33010602011771号