2013-02-27 85 views
1

我有一列JTable到我设置自定义TableCellRenderer和一个自定义TableCellEditor,返回包含的JTextField,JLabel的,Jbutton将和不确定JProgressBar
JTable中删除行

当我试图从删除行一个JPanel表模型,它是一个扩展了AbstractTableModel的类。这里是删除行的方法。

public void removeRow(int row) { 
myList.remove(row); 
fireTableRowsDeleted(row, row); 
} 

的TableModel.fireTableRowsDeleted(INT行)不工作作为我的视点表继续显示已删除的行。另一方面,方法TableModel.fireTableStructureChanged();正确更新JTable。我应该使用哪一个?我检查了DefaultTableModel.removeRow(int row)方法,它只使用fireTableRowsDeleted(int row);.

public class TableTest { 

    final static MyObjectTableModel model = new MyObjectTableModel(); 
    final static JTable table = new JTable(model); 
    private static Map<Integer, Future> mapSubmittedReadProgress = new HashMap<Integer, Future>(); 
    final static StartProgressActionListener progressActionListener = new StartProgressActionListener(); 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new TableTest().createGUI(); 
      } 
     }); 
    } 

    public static class MyObjectTableModel extends AbstractTableModel { 

     private LinkedList<MyObject> myList; 

     public MyObjectTableModel() { 
      super(); 
      myList = new LinkedList<MyObject>(); 
     } 

     public MyObjectTableModel(SortedSet<MyObject> myObjects) { 
      super(); 
      this.myList = new LinkedList<MyObject>(myObjects); 
     } 

     public void addRow(MyObject myObject) { 
      myList.add(myObject); 
      fireTableRowsInserted(myList.size() - 1, myList.size() - 1); 
     } 

     public void removeRow(int row) { 
      myList.remove(row); 
      fireTableRowsDeleted(row, row); 
//  fireTableStructureChanged(); 
     } 

     @Override 
     public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 
      myList.set(rowIndex, (MyObject) aValue); 
      fireTableCellUpdated(rowIndex, 0); 
     } 

     @Override 
     public int getRowCount() { 
      return myList.size(); 
     } 

     @Override 
     public int getColumnCount() { 
      return 1; 
     } 

     @Override 
     public Class<?> getColumnClass(int columnIndex) { 
      switch (columnIndex) { 
       case 0: 
        return MyObject.class; 
       default: 
        throw new IllegalArgumentException("invalid column: " + columnIndex); 
      } 
     } 

     @Override 
     public Object getValueAt(int rowIndex, int columnIndex) { 
      switch (columnIndex) { 
       case 0: 
        return myList.get(rowIndex); 
       default: 
        throw new IllegalArgumentException("invalid column: " + columnIndex); 
      } 
     } 

     public MyObject getMyObjectAt(int row) { 
      return myList.get(row); 
     } 

     @Override 
     public boolean isCellEditable(int rowIndex, int columnIndex) { 
      return true; 
     } 

     public int getIndexOf(MyObject myObject) { 
      return myList.indexOf(myObject); 
     } 
    } 

    private static void createGUI() { 
     JFrame f = new JFrame("TableTest"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     for (int i = 0; i < 16; i++) { 
      MyObject myObject = new MyObject(); 
      myObject.setText1("" + i); 
      model.addRow(myObject); 
     } 
     table.setOpaque(false); 
     table.setShowGrid(false); 
     table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
//  table.getSelectionModel().addListSelectionListener(new SelectionListener()); 
     table.setDefaultRenderer(MyObject.class, new MyTableCellRenderer()); 
     table.setDefaultEditor(MyObject.class, new MyTableCellEditor()); 
     table.setFillsViewportHeight(true); 
     f.add(new JScrollPane(table)); 

     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    private static class MyTableCellEditor extends AbstractCellEditor implements TableCellEditor { 

     private MyObjectPanel myObjectPanel = new MyObjectPanel(model, table); 
     private transient List<CellEditorListener> listeners; 

     public MyTableCellEditor() { 
      myObjectPanel.addStartProgressActionListener(progressActionListener); 
      listeners = new ArrayList<>(); 
     } 

     @Override 
     public boolean isCellEditable(EventObject e) { 
      return true; 
     } 

     @Override 
     public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 
      MyObject myObject = (MyObject) value; 
      myObjectPanel.setMyObject(myObject, row); 
      return myObjectPanel; 
     } 

     @Override 
     public Object getCellEditorValue() { 
      MyObject myObject = myObjectPanel.getMyObject(); 
      return myObject; 
     } 

     @Override 
     public void addCellEditorListener(CellEditorListener l) { 
      listeners.add(l); 
     } 

     @Override 
     public void removeCellEditorListener(CellEditorListener l) { 
      listeners.remove(l); 
     } 

     @Override 
     protected void fireEditingStopped() { 
      ChangeEvent ce = new ChangeEvent(this); 
      for (int i = listeners.size() - 1; i >= 0; i--) { 
       ((CellEditorListener) listeners.get(i)).editingStopped(ce); 
      } 
     } 
    } 

    private static class MyTableCellRenderer implements TableCellRenderer { 

     private MyObjectPanel myObjectPanel = new MyObjectPanel(model, table); 

     public MyTableCellRenderer() { 
      myObjectPanel.addStartProgressActionListener(progressActionListener); 
//   setOpaque(false); 
      int cWidth = table.getWidth(); 
//   setSize(new Dimension(cWidth, 1000)); 
     } 

     @Override 
     public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 
      MyObject myObject = (MyObject) value; 
      myObjectPanel.setMyObject(myObject, row); 
      table.setRowHeight(row, myObjectPanel.getPreferredSize().height); 
      return myObjectPanel; 
     } 
    } 

    private static class StartProgressActionListener implements ActionListener { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      if(table.isEditing()) { 
       table.getCellEditor().stopCellEditing(); 
      } 
      final ExecutorService executor = Executors.newFixedThreadPool(1); 
      Runnable progressRunnable = new ProgressRunnable(table.getSelectedRow()); 
      final Future<?> submit = executor.submit(progressRunnable); 
      mapSubmittedReadProgress.put(table.getSelectedRow(), submit); 
     } 
    } 

    private static class ProgressRunnable implements Runnable { 

     private ExecutorService executor; 
     private long beT; 
     private int dur = 30; // s 
     private int progress = 0; 
     private int row; 

     public ProgressRunnable(int row) { 
      this.row = row; 
      beT = System.currentTimeMillis(); 
     } 

     @Override 
     public void run() { 
      boolean abort = false; 
      int i = 0; 
      while (i <= dur && !abort) { 
       final long curT = System.currentTimeMillis(); 
       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        abort = true; 
        executor.shutdown(); 
       } 
       if (Thread.currentThread().isInterrupted()) { 
        abort = true; 
        executor.shutdown(); 
       } 
       progress = (int) Math.round(100 * ((double) (curT - beT)/1000)/dur); 
       MyObject myObject = new MyObject(); 
       myObject.setProgress(progress); 
       table.setValueAt(myObject, row, 0); 
       i++; 
      } 
     } 
    } 
} 


为MyObject:

public class MyObject { 
    private String text1; 
    private String text2; 
    private int progress; 

    public String getText1() { 
     return text1; 
    } 

    public void setText1(String text1) { 
     this.text1 = text1; 
    } 

    public String getText2() { 
     return text2; 
    } 

    public void setText2(String text2) { 
     this.text2 = text2; 
    } 

    public int getProgress() { 
     return progress; 
    } 

    public void setProgress(int progress) { 
     this.progress = progress; 
    } 
} 


MyObjectPanel:

public class MyObjectPanel extends javax.swing.JPanel { 

private int row; 
private MyObjectTableModel model; 
private JTable table; 

/** 
* Creates new form MyObjectPanel 
*/ 
public MyObjectPanel() { 
    initComponents(); 
} 

MyObjectPanel(MyObjectTableModel model, JTable table) { 
    this.model = model; 
    this.table = table; 
    initComponents(); 
} 

/** 
* 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() { 

    jTextField1 = new javax.swing.JTextField(); 
    jTextField2 = new javax.swing.JTextField(); 
    jProgressBar1 = new javax.swing.JProgressBar(); 
    btnStart = new javax.swing.JButton(); 
    btnStop = new javax.swing.JButton(); 
    btnClose = new javax.swing.JButton(); 

    btnStart.setText("Start"); 

    btnStop.setText("Stop"); 

    btnClose.setText("Close"); 
    btnClose.addActionListener(new java.awt.event.ActionListener() { 
     public void actionPerformed(java.awt.event.ActionEvent evt) { 
      btnCloseActionPerformed(evt); 
     } 
    }); 

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); 
    this.setLayout(layout); 
    layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
      .addContainerGap() 
      .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addComponent(jTextField1) 
      .addComponent(jTextField2) 
      .addComponent(jProgressBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 
      .addGroup(layout.createSequentialGroup() 
      .addComponent(btnStart) 
      .addGap(18, 18, 18) 
      .addComponent(btnStop) 
      .addGap(18, 18, 18) 
      .addComponent(btnClose) 
      .addGap(0, 199, Short.MAX_VALUE))) 
      .addContainerGap())); 
    layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
      .addContainerGap() 
      .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
      .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) 
      .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
      .addGap(18, 18, 18) 
      .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
      .addGap(18, 18, 18) 
      .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 
      .addComponent(btnStart) 
      .addComponent(btnStop) 
      .addComponent(btnClose)) 
      .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); 
}// </editor-fold> 

private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) { 
    System.out.println("getMyObjectRow() : " + getMyObjectRow()); 
    table.getCellEditor().stopCellEditing(); 
    model.removeRow(getMyObjectRow()); 
} 
// Variables declaration - do not modify 
private javax.swing.JButton btnClose; 
private javax.swing.JButton btnStart; 
private javax.swing.JButton btnStop; 
private javax.swing.JProgressBar jProgressBar1; 
private javax.swing.JTextField jTextField1; 
private javax.swing.JTextField jTextField2; 
// End of variables declaration 

void setMyObject(MyObject myObject, int row) { 
    this.row = row; 
    jTextField1.setText(myObject.getText1()); 
    jTextField2.setText(myObject.getText2()); 
    jProgressBar1.setValue(myObject.getProgress()); 
} 

int getMyObjectRow() { 
    return this.row; 
} 

MyObject getMyObject() { 
    MyObject myObject = new MyObject(); 
    myObject.setText1(jTextField1.getText()); 
    myObject.setText2(jTextField2.getText()); 
    myObject.setProgress(jProgressBar1.getValue()); 
    return myObject; 
} 

void addStartProgressActionListener(ActionListener progressActionListener) { 
    btnStart.addActionListener(progressActionListener); 
} 


编辑:工作SSCCE显示使用NetBeans GUI构建器面板上的关闭问题。这似乎是一个索引问题,但无法找到究竟是什么。稍后我会尝试在进度条工作时发布完整的示例。

编辑2:当单元格获得焦点时,我的进度条未更新,出现问题。关闭问题已解决。

+2

_TableModel.fireTableRowsDeleted(int row)not working_我怀疑这一点。张贴您的'AbstractTableModel'的完整代码,或者更好地发布[SSCCE](http://sscce.org)。在任何情况下,您都不需要调用'fireTableStructureChanged' – 2013-02-27 13:38:44

+0

您确定要删除Event Dispatch Thread上的行吗? – Robin 2013-02-27 14:41:54

+0

我该如何确定?我必须从EDT上的模型调用removeRow(int row)方法吗? – jerome 2013-02-27 14:45:16

回答

1

我试过你的TableModel,它工作正常。您的代码中的其他位置必须存在问题。我找不到MyObject,所以默认渲染器使用Object#toString()来显示一个空的。

public class TableTest { 

    private static class MyObject { 
     // empty 
    } 

    private static class MyObjectTableModel extends AbstractTableModel { 
     // no change 
    } 

    private static void createGUI() { 
     JFrame f = new JFrame("TableTest"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     final MyObjectTableModel model = new MyObjectTableModel(); 
     for (int i = 0; i < 16; i++) { 
      model.addRow(new MyObject()); 
     } 
     JTable table = new JTable(model); 
     f.add(new JScrollPane(table)); 
     f.add(new JButton(new AbstractAction("Remove") { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       model.removeRow(0); 
      } 
     }), BorderLayout.SOUTH); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new TableTest().createGUI(); 
      } 
     }); 
    } 
} 
+0

谢谢你,我将使用你的例证和邮政编码,这将更好地反映我在做什么,我可以重现我的问题。 – jerome 2013-02-27 17:31:11

+0

我很困惑。编辑器和渲染器都会调用缺少的构造函数。当我调用'table'构造函数时,关闭按钮可以工作,所以我想我们知道你的'removeRow'工作。现在这是一个不同的问题吗? – 2013-02-28 12:40:50

+0

是的,removeRow现在可以工作了,当单元格获得焦点时,我的进度条有另一个问题。代码已更新以显示问题。 – jerome 2013-03-04 08:19:59