我still正在努力应对应自动更新的JTable
。
情况如下:
我实例化MyTable
(扩展JTable
),并在我的UI类(MyView
)中设置它。 MyTable
类接受UI类和包含逻辑作为参数的类的实例:
...
private JPanel createTablePanel() {
tablePanel = new JPanel();
myTable = new MyTable(this,mymeth);
setMyTable(myTable);
JScrollPane scrollPane = new JScrollPane(getMyTable());
tablePanel.add(scrollPane);
return tablePanel;
}
MyTable
本身如下所示。设置了AbstractTableModel
(MyTableModel
)的扩展名。 TableModelListener
的扩展名设置为模型。最后,ListSelectionListener
的扩展名设置为模型的SelectionModel
。
public class MyTable extends JTable implements TableModelListener
{
public MyTable(MyView myView, MyMethods mymeth)
{
AbstractTableModel tableModel = new MyTableModel(mymeth);
setModel(tableModel);
getModel().addTableModelListener(new MyTableModelListener());
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
setCellSelectionEnabled(true);
getColumnModel().getSelectionModel().addListSelectionListener(new MyTableSelectionListener(this, mymeth, myView));
setPreferredScrollableViewportSize(this.getPreferredSize());
}
}
让我们快速浏览一下模型的构造函数。
public MyTableModel(MyMethods mymeth) {
dataObject = new MyData(mymeth);
myData = dataObject.getMyData();
colTitles = dataObject.getColTitles();
}
MyData
编译表格的数据:Vector<Vector<Object>>
,由三个Vector<Object>
(表数据)和一个String[]
(列标题)组成。数据本身来自图mymeth
,逻辑类'实例。
只要单击表列,就会实例化一个弹出窗口(即JOptionPane
)对象,该对象会显示所选列中第3行的值选择。用户选择一个值,该值设置为数据模型。 注意之后表格更新的方式。
public MyOptionPane(int i, MyMethods mymeth, MyView myView) {
this.view = myView;
String sourceString = mymeth.getSourceString(i); // Gets a String from a
String[]. In this Array, the order is the same as in the table.
String tag = null;
tag = (String) JOptionPane.showInputDialog(this, "Choose a tag for \"" + sourceString + "\"", "String tagging" , JOptionPane.PLAIN_MESSAGE, null, myView.getTags().toArray(), myView.getTags().get(0));
mymeth.setTag(i, tag);
// This is where fireTableDataChanged() didn't work, but this did
MyTableModel model = new MyTableModel(mymeth); // New model instance
view.getMyTable().setModel(model); // reset new model to table
}
这很有效。但是,根据我的阅读,我可以简单地在模型上调用fireTableDataChanged()
,表格应该自行更新。但是,这不起作用。用户kleopatra在之前的帖子中有commented个答案:
不要从模型外部的任何代码调用任何模型的fireXX方法。 而是在发生任何变化时实施模型
所以:我可以在这样的结构中调用fireTableDataChanged()
吗?如果是的话,在哪里以及如何?
提前感谢所有的启蒙!
答案 0 :(得分:4)
从我读过的内容我可以简单地在模型上调用fireTableDataChanged()并且表应该自行更新
您的程序不会在模型上调用fireXXX方法。 TableModel本身负责在模型中的任何数据发生更改时调用这些方法。查看Swing教程中的Creating a Table Model示例。 setValueAt(...)方法显示了如何调用适当的fireXXX方法。
如果您创建一个全新的TableModel,则需要使用setModel()方法。
Kleopatra的评论是所有fireXXX方法都显示在TableModel类本身内部调用。如果您想了解这是如何完成的,那么请查看DefaultTableModel的源代码。如果有你何时调用fireTableDataChanged()方法以及其他fireXXX方法的例子。
答案 1 :(得分:3)
您不必替换整个模型来更新单行。相反,更新受影响的单元格,让setValueAt()
触发所需的事件,如here所示。或者,此相关example使用DefaultTableModel
为您处理事件,如@mKorbel&amp; @camickr。
如果您与AbstractTableModel
保持联系,请考虑List<List<MyData>>
,除非您出于其他原因需要Vector
。
答案 2 :(得分:2)
不回答您的问题,建议使用DefaultTableModel
如果您不需要限制某些内容JTable
,这是非常好的理由,那么您就无法使用AbstractTableModel,如果您实施DefaultTableModel,最佳工作仍然是},使用DefaultTableModel
您永远不会关心,FireXxxXxxChanged()
您必须使用setXxx()
方法中的哪一个,
答案 3 :(得分:0)
这是一个ArrayList
Person
的简单程序,使用ArrayList
中的数据填充表格,并使用AbstractTableModel
更新fireTableDataChanged()
。希望这有帮助
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
/**
*
* @author razak
*/
public class Table extends javax.swing.JFrame {
ArrayList<Person> records; //arrayList of persons
AbstractTable tableModel; //table model --inner class
/**
* Creates new form Table
*/
public Table() {
records = new ArrayList<>();
tableModel = new AbstractTable(records);
addData();
initComponents();
recordTable.setModel(tableModel);
}
/**
* Adds test values to the table
*/
private void addData() {
records.add(new Person("Tester", 21));
records.add(new Person("Kofi", 20));
records.add(new Person("Razak", 251));
records.add(new Person("Joseph", 21));
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
recordTable = new javax.swing.JTable();
nameLabel = new javax.swing.JLabel();
ageLabel = new javax.swing.JLabel();
nameTextField = new javax.swing.JTextField();
ageTextField = new javax.swing.JTextField();
addButton = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
recordTable.setModel(tableModel);
jScrollPane1.setViewportView(recordTable);
nameLabel.setText("Name");
ageLabel.setText("Age");
addButton.setText("Add");
addButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
addButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGap(52, 52, 52)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(nameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(ageLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(40, 40, 40)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(nameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 151, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createSequentialGroup()
.addComponent(ageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 61, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(66, 66, 66)
.addComponent(addButton, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(39, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(16, 16, 16)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(nameLabel)
.addComponent(nameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(ageLabel)
.addComponent(ageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 31, Short.MAX_VALUE)
.addComponent(addButton)
.addGap(18, 18, 18)))
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 173, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
pack();
}// </editor-fold>
/**
* When add button is clicked
*
* @param evt
*/
private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
String name = nameTextField.getText();
int age = Integer.parseInt(ageTextField.getText());
records.add(new Person(name, age));
tableModel.fireTableDataChanged();
}
/**
* Inner class
*/
class AbstractTable extends AbstractTableModel {
String col[]; //column names
ArrayList<Person> data; //arrayList to populate table
AbstractTable(ArrayList<Person> record) {
this.col = new String[]{"Name", "Age"};
data = record;
}
//get number of records
@Override
public int getRowCount() {
return data.size();
}
//get number of columns
@Override
public int getColumnCount() {
return col.length;
}
//get a value form the table
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Person person = data.get(rowIndex);
if (columnIndex == 0) {
return person.getName();
} else if (columnIndex == 1) {
return person.getAge();
}
return null;
}
//set value at a particular cell
public void setValueAt(Person person, int row, int column) {
data.add(row, person);
fireTableCellUpdated(row, column);
}
//get column name
public String getColumnName(int column) {
return col[column];
}
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(Table.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(Table.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(Table.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(Table.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Table().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton addButton;
private javax.swing.JLabel ageLabel;
private javax.swing.JTextField ageTextField;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel nameLabel;
private javax.swing.JTextField nameTextField;
private javax.swing.JTable recordTable;
// End of variables declaration
}
/**
* Person class
* @author razak
*/
public class Person {
private final String name; //name
private final int age; //age
//constructor
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//return name
public String getName() {
return name;
}
//returns age
public int getAge() {
return age;
}
}