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 getData() {
		FileReader fr;
		File file = new File(
				"E:/my.txt");
		int b;
		StringBuffer sb = new StringBuffer();
		List s = new ArrayList();
		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 getData() 方法得到的List构建数据模型
	//此处使用的外部文件中,每一行的字符串用空格分成四个部分
	//例如,其中一行为:2013-03-18 11:50:55   传感器1    报警,对应表格的一行
	public AbstractTableModel getTableModel() {
		
		return new AbstractTableModel() {
			
			List 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();
			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();
	}
}

 修改版本,实时更新:

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 getData() {
		FileReader fr;
		File file = new File(
				"E:/my.txt");
		int b;
		StringBuffer sb = new StringBuffer();
		List s = new ArrayList();
		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 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 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 getData() {
		FileReader fr;
		File file = new File(
				"E:/my.txt");
		int b;
		StringBuffer sb = new StringBuffer();
		List s = new ArrayList();
		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 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();
		
	}
}

效果一样 。

你可能感兴趣的:(JTable数据实时更新)