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();
- }
- }
效果一樣 。