JTable Вставляют строку и обновление

Я пытаюсь создать простое приложение, где JTable обновляется и обновился после того, как данные изменяются. Структура следующие. 1) Класс, Основной, который содержит JFrame, детали JTable. 2) Класс SampleTableModel, который расширяет AbstractTableModel. Я переопределяю большинство методов.

import javax.swing.table.*;
import java.util.*;

public class SampleTableModel extends AbstractTableModel {

    public SampleTableModel() {
        // this.addTableModelListener(
    }
    String[] columnNames = {"A", "B", "C", "D", "E"};
    int[][] data = {{1, 2, 3, 4, 5}, {5, 6, 7, 8, 9}, {12, 13, 14, 15, 16}};
    Vector dataVector = new Vector();

    public Object getValueAt(int rowIndex, int columnIndex) {
        return data[rowIndex][columnIndex];
    }

    public int getColumnCount() {
        return 5;
    }

    public int getRowCount() {
        return 3;
    }

    public String getColumnName(int columnIndex) {
        return columnNames[columnIndex];
    }

    public void setValueAt(Object value, int row, int column) {
        data[row][column] = 99;
    }

    public void notifyTable(AEMessage message) {
        /*
         * This method will be called from another class to update JTable.
         * */
        data[0][1] = 999;
        data[0][2] = 8838;
        data[1][1] = 8883;
        fireTableRowsUpdated(0, 3);
    }
}

Как Вы видите, notifyTable назовут от другого класса (который является на самом деле потоком - который часто называет этот метод), проблема, я не вижу, что данные изменяются в JTable. Я вижу только инициализируемые данные. В основном классе - я устанавливаю как это -

RVJDataTable.setModel(new SampleTableModel());

Я использую DefaultTableModel вместо Краткого обзора один для вставки данных.

Это - он основной класс JTable -

 import javax.swing.event.TableModelListener;
  import javax.swing.event.TableModelEvent;
   public class MainWindow extends javax.swing.JFrame implements TableModelListener {

    public MainWindow() {
    initComponents();
}

     private void initComponents() {

    jScrollPane1 = new javax.swing.JScrollPane();
   //    RVTableModel model = new RVTableModel();
    TableModelWrapper wrap = new TableModelWrapper();
    RVDataTable = new javax.swing.JTable();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    RVDataTable.setModel(wrap.getModel());

    RVDataTable.getModel().addTableModelListener(this);

   // RVDataTable.
    jScrollPane1.setViewportView(RVDataTable);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGap(57, 57, 57)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 552, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap(105, Short.MAX_VALUE))
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
            .addContainerGap(25, Short.MAX_VALUE)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 193, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addGap(82, 82, 82))
    );

    pack();
}// </editor-fold>

/**
* @param args the command line arguments
*/
public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new MainWindow().setVisible(true);
        }
    });
}

public void tableChanged(TableModelEvent evt){
    System.out.println(evt.getFirstRow());
}

// Variables declaration - do not modify
private javax.swing.JTable RVDataTable;
private javax.swing.JScrollPane jScrollPane1;
// End of variables declaration

} после класса используется для определения DefaultTableModel:

import javax.swing.table.*;
import javax.swing.event.*;
import java.util.*;
public class TableModelWrapper {
public DefaultTableModel getModel(){
    Vector dataVec = new Vector();
    String[] arr = {"ABS","ASAAS","ASAsA","AsaSA"};
    Vector rowVec = new Vector();
    for(int i=0;i<4;i++)
    rowVec.add(i,arr[i] );

    for(int i=0;i<5;i++)
        dataVec.add(i, rowVec);

    Vector columnNames = new Vector();
    columnNames.add("FIRST");
    columnNames.add("SECOND");
    columnNames.add("THIIRD");
    columnNames.add("FOURTH");
    //columnNames.add("FIFTH");
    DefaultTableModel model = new DefaultTableModel(dataVec,columnNames);
    return model;

}

public Object[] getRecord(){
    String[] arr = {"hhaHHA","HHHDS","NHHHSS","PQPPPQ"};
    return arr;
}

} и follwing класс добавляет запись каждые 5 секунд с помощью класса Stock.

   public class Updater {

public static void main(String[] args){
    Stock stock =new Stock();
    stock.start();
}

} класс Stock расширяет Поток {

//RVTableModel model = null;
TableModelWrapper wrap = null;
public Stock(){
   wrap = new TableModelWrapper();
}

public void run(){
    try{
    while(true){
        wrap.getModel().addRow(wrap.getRecord());
        wrap.getModel().fireTableRowsInserted(wrap.getModel().getRowCount()     +1,wrap.getModel().getRowCount()+1);
        sleep(5000);
    }
    }
    catch(InterruptedException e){
        System.out.println(e);
    }
}

} я не вижу, что JTable обновляется.

1
задан Bhargav Rao 28 February 2017 в 12:18
поделиться

2 ответа

В целом, Swing не является потокобезопасным. Рассмотрите возможность использования EventQueue.invokeLater(), упомянутого здесь.

Дополнение: Учитывая ваш обновленный пример, попробуйте что-нибудь вроде этого:

@Override
public void run() {
    while (true) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                wrap.getModel().addRow(wrap.getRecord());
            }
        });
        try {
            Thread.sleep(5000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

Дополнение: SwingWorker, обсуждаемый здесь, является еще одним альтернативным средством обновления GUI из другого потока.

1
ответ дан 3 September 2019 в 00:14
поделиться

Судя по предоставленному коду, похоже, что он должен работать, но код не завершен, поэтому я не могу сказать наверняка. Может быть, ваш «другой» класс имеет ссылку на неправильную TableModel?

Кроме того, в ваших данных нет ничего особенного, так почему бы просто не использовать DefaultTableModel. Затем вы можете обновить таблицу, используя:

table.setValueAt( 123, 0, 0 );
table.setValueAt( 456, 0, 1 );

Если вам нужна дополнительная помощь, опубликуйте свой SSCCE .

1
ответ дан 3 September 2019 в 00:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: