I'm trying to implement the MVC on a test example. How can i update the table when there is a change
Class: Model
class valueUpdater extends Thread {
private String sValue;
public valueUpdater() {
this.start();
}
public String getValue() {
return this.sValue;
}
public void run() {
try {
for (int i = 0; i <= 100; i++) {
this.sValue = String.valueOf(i);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Class: Controller
public class CLS_Controller2 extends AbstractTableModel {
private static final long serialVersionUID = -5603593230985106202L;
private String[] sArrColumns = { "Nombre", "Valor" };
private ArrayList<valueUpdater> tListUpdater = new ArrayList<valueUpdater>();
public CLS_Controller2() {
super();
}
public void addRow(String sName) {
this.tListUpdater.add(new valueUpdater(sName));
this.fireTableDataChanged();
}
public void deleteRow(int iIndex) {
this.tListUpdater.remove(iIndex);
this.fireTableDataChanged();
}
@Override
public String getColumnName(int iColumn) {
return this.sArrColumns[iColumn];
}
@Override
public int getColumnCount() {
return this.sArrColumns.length;
}
@Override
public int getRowCount() {
return this.tListUpdater.size();
}
@Override
public Object getValueAt(int iRow, int iColumn) {
valueUpdater tValueUpdater = this.tListUpdater.get(iRow);
switch (iColumn) {
case 0:
return tValueUpdater.getRowName();
case 1:
return tValueUpdater.getValue();
default:
return null;
}
}
@Override
public void setValueAt(Object oValue, int iRow, int iColumn) {
valueUpdater tValueUpdater = this.tListUpdater.get(iRow);
switch (iColumn) {
case 0:
tValueUpdater.setRowName(oValue.toString());
break;
}
fireTableCellUpdated(iRow, iColumn);
}
@Override
public Class<String> getColumnClass(int iColumn) {
return String.class;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
}
Class: View
public class FRM_Main {
private JFrame frame;
private JTable table;
private CLS_Controller2 tModel;
private JTextField textField;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
FRM_Main window = new FRM_Main();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public FRM_Main() {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 476, 283);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.CENTER);
JScrollPane scrollPane = new JScrollPane();
JButton btnNewButton = new JButton("Add");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
tModel.addRow(textField.getText());
}
});
JButton btnNewButton_1 = new JButton("Delete");
textField = new JTextField();
textField.setColumns(10);
GroupLayout gl_panel = new GroupLayout(panel);
gl_panel.setHorizontalGroup(gl_panel
.createParallelGroup(Alignment.LEADING)
.addGroup(
gl_panel.createSequentialGroup()
.addContainerGap()
.addGroup(
gl_panel.createParallelGroup(
Alignment.LEADING)
.addComponent(
scrollPane,
GroupLayout.DEFAULT_SIZE,
440, Short.MAX_VALUE)
.addGroup(
Alignment.TRAILING,
gl_panel.createSequentialGroup()
.addComponent(
textField,
GroupLayout.PREFERRED_SIZE,
GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE)
.addPreferredGap(
ComponentPlacement.RELATED)
.addComponent(
btnNewButton)
.addPreferredGap(
ComponentPlacement.RELATED,
216,
Short.MAX_VALUE)
.addComponent(
btnNewButton_1)))
.addContainerGap()));
gl_panel.setVerticalGroup(gl_panel
.createParallelGroup(Alignment.LEADING)
.addGroup(
gl_panel.createSequentialGroup()
.addContainerGap()
.addComponent(scrollPane,
GroupLayout.PREFERRED_SIZE, 194,
GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(
gl_panel.createParallelGroup(
Alignment.BASELINE)
.addComponent(btnNewButton_1)
.addComponent(
textField,
GroupLayout.PREFERRED_SIZE,
GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE)
.addComponent(btnNewButton))
.addContainerGap(80, Short.MAX_VALUE)));
table = new JTable();
table.setShowVerticalLines(false);
table.setShowHorizontalLines(false);
table.setFillsViewportHeight(true);
tModel = new CLS_Controller2();
table.setModel(tModel);
scrollPane.setViewportView(table);
panel.setLayout(gl_panel);
}
}
I have read a lot about MVC but I'm still new. If someone can help me please. Thanks in advance.
Your
TableModel
is the model, and yourJTable
is the view. The call tosetModel()
causes the view to add itself as aTableModelListener
to the model; subsequent changes to the model notify the view to update itself based on anyTableModelEvent
received. In this complete example, both a button and a separate thread update the model.SwingWorker
, seen here, is another common approach that simplifies synchronizing access to shared data.A noted here, Swing uses separable model architecture, with the user controlling interaction. Except for the initial wiring, there isn't much for your controller to do.