问题
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.
回答1:
Your TableModel
is the model, and your JTable
is the view. The call to setModel()
causes the view to add itself as a TableModelListener
to the model; subsequent changes to the model notify the view to update itself based on any TableModelEvent
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.
来源:https://stackoverflow.com/questions/17680194/jtable-tablemodel-mvc-implementation-help