2013-04-25 83 views
5

我有一個需要單元驗證的JTable,用於用戶可以輸入文本的單元格。當用戶輸入無效文本時,單元格的邊框變爲紅色。JTable中的單元格驗證

我設法得到這個工作關聯一個二維數組來標記,如果每個單元格有錯誤或沒有。

問題是用戶必須能夠重新排列表(按列)。我必須在表格模型中存儲錯誤標誌,而不是分開。任何人有想法如何做到這一點?

+0

用戶只能一次編輯一個小區。在數據有效之前不要讓他們更新模型。由於模型中的所有數據應始終有效,因此我不認爲需要使用二維數組來追蹤錯誤。 – camickr 2013-04-25 21:22:47

+0

您還可以通過模型索引來定位「錯誤」狀態。這樣您可以根據需要將視圖索引轉換回模型索引。我喜歡camickr的建議 – MadProgrammer 2013-04-25 21:35:24

回答

4

我試過一種方法。我們可以使用TableCellRenderer並檢查單元格中的數據,如果數據有錯誤,則只需在RED中顯示它。在這裏我有一個StudentTableModel這將獲得的數據表。

Error Check

After Reordering

表顯示了細胞RED如果單元格中包含像'@', '#', '$'特殊字符。您仍然可以使用reorder表格,但渲染仍會照顧它。 AFAIK標誌不是實現這個所必需的。

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.EventQueue; 

import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.table.DefaultTableCellRenderer; 

import com.amarnath.DragDrop.StudentTableModel; 

public class TableErrorCheck { 

    private JFrame frame; 
    private JTable table; 


    private void createUI() { 

     frame = new JFrame(); 
     table = new JTable(); 
     table.setModel(new StudentTableModel()); 
     table.getColumnModel().getColumn(1).setCellRenderer(new ErrorCellRenderer()); 

     frame.setLayout(new BorderLayout()); 
     frame.add(new JScrollPane(table), BorderLayout.CENTER); 
     frame.setTitle("Table Error Check."); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     Runnable r = new Runnable() { 

      @Override 
      public void run() { 
       new TableErrorCheck().createUI(); 
      } 
     }; 

     EventQueue.invokeLater(r); 
    } 

} 

class ErrorCellRenderer extends DefaultTableCellRenderer { 

    private static final long serialVersionUID = 1L; 

    @Override 
    public Component getTableCellRendererComponent(JTable table, Object value, 
      boolean isSelected, boolean hasFocus, int row, int column) { 
     Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, 
       row, column); 

     if(value.toString().contains("@") || value.toString().contains("$") || value.toString().contains("#")) { 
      component.setBackground(Color.RED); 
     } else { 
      component.setBackground(Color.WHITE); 
     } 

     return component; 
    } 
} 


import java.util.ArrayList; 
import java.util.List; 

import javax.swing.table.AbstractTableModel; 

public class StudentTableModel extends AbstractTableModel { 

    private static final long serialVersionUID = 1L; 

    private List<StudentDO> data; 

    private List<String> columnNames; 

    public StudentTableModel() { 
     data = getTableData(); 
     columnNames = getTableColumnNames(); 
    } 

    public List<StudentDO> getData() { 
     return data; 
    } 

    public void setData(List<StudentDO> data) { 
     this.data = data; 
    } 

    @Override 
    public Class<?> getColumnClass(int columnIndex) { 
     switch (columnIndex) { 
     case 0: 
      return Boolean.class; 
     case 1: 
      return String.class; 
     case 2: 
      return String.class; 
     default: 
      return String.class; 
     } 
    } 

    @Override 
    public String getColumnName(int column) { 
     return columnNames.get(column); 
    } 

    @Override 
    public int getColumnCount() { 
     return columnNames.size(); 
    } 

    @Override 
    public int getRowCount() { 
     if(data == null) { 
      return 0; 
     } 
     return data.size(); 
    } 

    @Override 
    public boolean isCellEditable(int rowIndex, int columnIndex) { 
     if(columnIndex == 0 || columnIndex == 1) { 
      return true; 
     } else { 
      return false; 
     } 
    } 

    @Override 
    public Object getValueAt(int rowIndex, int columnIndex) { 
     switch (columnIndex) { 
     case 0: 
      return data.get(rowIndex).isSelect(); 
     case 1: 
      return data.get(rowIndex).getName(); 
     case 2: 
      return data.get(rowIndex).getAge(); 
     default: 
      return null; 
     } 
    } 

    @Override 
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 
     switch (columnIndex) { 
     case 0: 
      data.get(rowIndex).setSelect((Boolean) aValue); 
      break; 
     case 1: 
      data.get(rowIndex).setName(aValue == null ? null : aValue.toString()); 
      break; 
     case 2: 
      data.get(rowIndex).setAge(aValue == null ? new Integer(0) : Integer.parseInt(aValue.toString())); 
      break; 
     default: 
      break; 
     } 
    } 

    /** 
    * Add a row. 
    * @param index 
    * @param studentDO 
    */ 
    public void addRow(int index, StudentDO studentDO) { 
     data.add(index, studentDO); 
     fireTableDataChanged(); 
    } 

    private List<StudentDO> getTableData() { 
     List<StudentDO> list = new ArrayList<StudentDO>(); 

     for(int i = 0; i< 5; i++) { 
      StudentDO student = new StudentDO(); 
      student.setSelect(false); 
      student.setName("Stu " + i); 
      student.setAge(10 + i); 
      student.setIdentifier("ToapTable"); 

      list.add(student); 
     } 

     return list; 
    } 

    private List<String> getTableColumnNames() { 
     List<String> columnNames = new ArrayList<String>(); 
     columnNames.add("Select"); 
     columnNames.add("Name"); 
     columnNames.add("Age"); 

     return columnNames; 
    } 
} 

public class StudentDO { 

    private boolean select; 
    private String name; 
    private int age; 
     // Removed Getters and Setters . 
} 

P.S:請讓我知道這是否是好辦法與否。

+1

+1使用'TableCellRenderer'來突出顯示單元格。 – trashgod 2013-04-26 11:27:28

+0

@Che。謝謝。事實上,這是我的方法。但有兩個問題:1)某些單元驗證規則依賴於2個單元格2)如何遍歷單元格渲染器並檢查背景的顏色?這就是爲什麼我創建了一個2維數組來檢查錯誤...但是,這可以防止行排序(我的問題) – 2013-05-25 07:35:12

+0

@AlexandreGoncalves如果你需要做排序,那麼你需要保存行號。 – Amarnath 2013-05-25 17:15:00

6

也考慮定製TableCellEditor,看到here及以下。如here所示,添加InputVerifier是很好的選擇。

由於用戶必須能夠通過柱重新排序該表:

JTable提供了從模型轉換方法的座標,以查看座標 - convertColumnIndexToViewconvertRowIndexToView - 和從視圖座標轉換到模型座標 - convertColumnIndexToModelconvertRowIndexToModel

image