这是情况,代码如下
用户填写 3 个字段并按下“添加”按钮 => 创建一个 ToDoBean 并将其添加到一个 ToDoModel(扩展 AbstractTableModel),并使用模型中的 ToDoBean 的索引创建一个 Runnable。Runnable 通过 ScheduledExecutorService 立即启动。
Runnable 的目标是递减一个 int 直到它达到零。
一切正常。
现在用户还可以在 JTable 中选择一行并按下“删除”按钮以从列表中删除 ToDoBean。
我的问题是:当我删除 bean 时,看起来它也从 ScheduledExecutorService 中删除了。为什么?如何?事实上,这正是我所需要的,但我想了解这些机制。谢谢
编码:
package demo.todolist;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
public class ToDoFrame extends javax.swing.JFrame {
private final static int POOL_SIZE = 10;
private ToDoModel model = new ToDoModel();
private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(POOL_SIZE);
/** Creates new form ToDoFrame */
public ToDoFrame() {
initComponents();
}
private ToDoBean createToDoBean() {
return new ToDoBean(jTextField1.getText(), jTextField2.getText(), Long.valueOf(jTextField3.getText()));
}
private void addToList(ToDoBean toDoBean) {
model.addToDoBean(toDoBean);
scheduledExecutorService.schedule(new UpdateRunnable(model.getRowCount() - 1), 0,TimeUnit.SECONDS);
}
private class UpdateRunnable implements Runnable {
private int index;
public UpdateRunnable(int index) {
this.index = index;
}
@Override
public void run() {
System.out.println("Task for index " + index + " started");
while (model.getToDoBeanAt(index).getDelay() > 0) {
try {
Thread.sleep(10000);
model.decreaseBeanAt(index);
System.out.println("Delay decreased at index " + index);
} catch (InterruptedException ex) {
Logger.getLogger(ToDoFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
System.out.println("Task for index " + index + " ended");
}
}
/** 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() {
GridBagConstraints gridBagConstraints;
jLabel1 = new JLabel();
jLabel2 = new JLabel();
jLabel3 = new JLabel();
jTextField1 = new JTextField();
jTextField2 = new JTextField();
jTextField3 = new JTextField();
jButton1 = new JButton();
jScrollPane1 = new JScrollPane();
jTable1 = new JTable();
jButton2 = new JButton();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
getContentPane().setLayout(new GridBagLayout());
jLabel1.setText("Name :");
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.anchor = GridBagConstraints.LINE_END;
gridBagConstraints.insets = new Insets(5, 5, 5, 5);
getContentPane().add(jLabel1, gridBagConstraints);
jLabel2.setText("Description :");
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = GridBagConstraints.LINE_END;
gridBagConstraints.insets = new Insets(5, 5, 5, 5);
getContentPane().add(jLabel2, gridBagConstraints);
jLabel3.setText("Delai (seconds) :");
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = GridBagConstraints.LINE_END;
gridBagConstraints.insets = new Insets(5, 5, 5, 5);
getContentPane().add(jLabel3, gridBagConstraints);
jTextField1.setText("my name ");
jTextField1.setMinimumSize(new Dimension(50, 25));
jTextField1.setPreferredSize(new Dimension(80, 27));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.anchor = GridBagConstraints.LINE_START;
gridBagConstraints.insets = new Insets(5, 5, 5, 5);
getContentPane().add(jTextField1, gridBagConstraints);
jTextField2.setText("some description");
jTextField2.setMinimumSize(new Dimension(145, 25));
jTextField2.setPreferredSize(new Dimension(145, 27));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.anchor = GridBagConstraints.LINE_START;
gridBagConstraints.insets = new Insets(5, 5, 5, 5);
getContentPane().add(jTextField2, gridBagConstraints);
jTextField3.setHorizontalAlignment(JTextField.TRAILING);
jTextField3.setText("5");
jTextField3.setMinimumSize(new Dimension(25, 25));
jTextField3.setPreferredSize(new Dimension(25, 27));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = GridBagConstraints.LINE_START;
gridBagConstraints.insets = new Insets(5, 5, 5, 5);
getContentPane().add(jTextField3, gridBagConstraints);
jButton1.setText("Add");
jButton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
getContentPane().add(jButton1, new GridBagConstraints());
jScrollPane1.setMinimumSize(new Dimension(280, 150));
jScrollPane1.setPreferredSize(new Dimension(280, 275));
jTable1.setModel(model
);
jScrollPane1.setViewportView(jTable1);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 3;
gridBagConstraints.gridwidth = 3;
getContentPane().add(jScrollPane1, gridBagConstraints);
jButton2.setText("Remove");
jButton2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jButton2ActionPerformed(evt);
}
});
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 2;
gridBagConstraints.insets = new Insets(5, 5, 5, 5);
getContentPane().add(jButton2, gridBagConstraints);
pack();
}// </editor-fold>
private void jButton1ActionPerformed(ActionEvent evt) {
addToList(createToDoBean());
}
private void jButton2ActionPerformed(ActionEvent evt) {
int rowIndex = jTable1.getSelectedRow();
model.removeToDoBeanAt(rowIndex);
/*
* the ToDoBean is removed from the list
* the table is updated
* the scheduledExecutorService is also updated ... why?
*/
}
/**
* @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(ToDoFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(ToDoFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(ToDoFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(ToDoFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new ToDoFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private JButton jButton1;
private JButton jButton2;
private JLabel jLabel1;
private JLabel jLabel2;
private JLabel jLabel3;
private JScrollPane jScrollPane1;
private JTable jTable1;
private JTextField jTextField1;
private JTextField jTextField2;
private JTextField jTextField3;
// End of variables declaration
}
包demo.todolist;
导入 java.util.ArrayList;导入 java.util.List;导入 javax.swing.table.AbstractTableModel;
公共类 ToDoModel 扩展 AbstractTableModel {
protected List<ToDoBean> list = new ArrayList<ToDoBean>(); private final static String[] columns = {"Name", "Description", "Remaining"}; private final static Class[] columnsClass = {String.class, String.class, Long.class}; public final static int[] columnWidths = {80, 150, 50}; // 280 public ToDoModel() { } public ToDoModel(List<ToDoBean> list) { super(); this.list = list; } @Override public Class getColumnClass(int columnIndex) { return columnsClass[columnIndex]; } @Override public int getRowCount() { return list.size(); } @Override public int getColumnCount() { return columns.length; } @Override public String getColumnName(int col) { return columns[col]; } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return false; } @Override public Object getValueAt(int rowIndex, int columnIndex) { ToDoBean result = list.get(rowIndex); switch (columnIndex) { case 0: return result.getName(); case 1: return result.getDescription(); default: return result.getDelay(); } } @Override public void setValueAt(Object obj,int rowIndex, int columnIndex) { ToDoBean result = list.get(rowIndex); switch (columnIndex) { case 0: result.setName((String) obj); break; case 1: result.setDescription((String) obj); break; default: result.setDelay((Long) obj); } list.set(rowIndex, result); this.fireTableCellUpdated(rowIndex, columnIndex); } public void addToDoBean(ToDoBean w) { list.add(w); fireTableDataChanged(); } public void addToDoBeanList(List l) { list.addAll(l); fireTableDataChanged(); } public ToDoBean getToDoBeanAt(int row) { return list.get(row); } public ToDoBean removeToDoBeanAt(int row) { ToDoBean pos = list.remove(row); fireTableDataChanged(); return pos; } public long decreaseBeanAt(int rowIndex) { ToDoBean result = list.get(rowIndex); long remaining = result.getDelay(); result.setDelay(--remaining); this.fireTableCellUpdated(rowIndex, 2); return remaining; } }
包demo.todolist;
公共类 ToDoBean {
private String name; private String description; private long delay; public ToDoBean(String name, String description, long delay) { this.name = name; this.description = description; this.delay = delay; } public ToDoBean() { } public long getDelay() { return delay; } public void setDelay(long delay) { this.delay = delay; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void decrease() { delay--; } }