2012-06-25 68 views
1

我有一個相當複雜的JTable,我正在研究。行和列的數量由列表構成。然後取決於單元格編輯器需要更改的行的哪一列。當我尋找一個解決方案的goggling時,我發現這個: http://www.java2s.com/Code/Java/Swing-Components/EachRowwithdifferentEditorExample.htm自定義TableCellEditor只適用於1 Column Dispite應用於所有

我把那個代碼變成了原樣並運行它,以確保它能夠工作在當前的Java版本中。所以我將它工作到了我已經構建的JTable中,但似乎正在發生的事情是,當我將它應用於多個列時,它最終只能爲第一列工作。

我整理了一段完全可執行的代碼段,我已經評論並設置了模擬我的數據庫數據。代碼是相當體面的評論,所以應該很容易遵循。這個例子至少對我來說仍然會產生問題。

如果您有任何人可以看到最新的錯誤,我將非常感謝幫助。

import java.awt.*; 
import java.awt.event.*; 
import java.util.List; 
import java.util.*; 
import javax.swing.*; 
import javax.swing.event.*; 
import javax.swing.table.*; 


public class EachRowEditorExample extends JFrame { 

    public EachRowEditorExample() { 
     super("EachRow Editor Example"); 
     List<Membership> _Memberships = new ArrayList<Membership>(); 
     DefaultTableModel DataModel; 

     //Lets Start by simluating the data. 
     for (int z = -2; z < 10; z++) 
     { 
      Membership m = new Membership(); 
      m.setId(z); 
      if (z == -2) 
      { 
       m.setMembership("Employee"); 
       m.setEft(false); 
      } 
      else if (z == -1) 
      { 
       m.setMembership("NONE"); 
       m.setEft(false); 
      } 
      else 
      { 
       m.setMembership("Membership " + z); 
       if (z < 3) 
        m.setEft(true); 
       else 
        m.setEft(false); 
      } 
      _Memberships.add(m); 
     } 

     //******************************************************* 
     // Starts Copy and paste from Program 
     //******************************************************* 
     //lets build our Data Model 
     int size = _Memberships.size(); 
     Object[][] rows = new Object[size][]; 
     String[] cols = new String[size]; 
     int x = 0; 
     for(Iterator<Membership> i = _Memberships.iterator(); i.hasNext();) 
     { 
      Membership side = i.next(); 
      cols[x] = side.getMembership(); 
      Object[] row = new Object[size]; 
      int b = 0; 
      for(Iterator<Membership> j = _Memberships.iterator(); j.hasNext();) 
      { 
       Membership top = j.next(); 
       if (side.getId() == top.getId() && (side.isEft() && top.isEft())) 
       { 
        row[b] = null; 
       } 
       else 
        row[b] = NUHPADX(side.getId(), top.getId()); 
       b++; 
      } 
      rows[x] = row; 
      x++; 
     } 
     DataModel = new DefaultTableModel(rows,cols); 


     //Now Lets create our JTable and configure it. 
     JTable table = new JTable(DataModel) { 
      @Override 
      public boolean isCellEditable(int rowIndex, int columnIndex) { 
       Object t = getValueAt(rowIndex, rowIndex); 
       if (t == null) 
        return false; 
       else 
        return true; 
      } 

      @Override 
      public Component prepareRenderer(TableCellRenderer renderer, int row, int column) 
      { 
       Component c = super.prepareRenderer(renderer, row, column); 

       Object t = getValueAt(row, column); 
       if (t == null) 
       { 
        c.setBackground(Color.black); 
       } 
       else 
       { 
        Color PRIMARY_ROW_COLOR = Color.white; 
        Color ALTERNATE_ROW_COLOR = new Color(0xA9F1ED); 

        //even index, selected or not selected 
        if (row % 2 == 0) 
        { 
         if (column % 2 == 0) 
          c.setBackground(PRIMARY_ROW_COLOR.darker()); 
         else 
          c.setBackground(PRIMARY_ROW_COLOR); 
        } 
        else 
        { 
         if (column % 2 == 0) 
          c.setBackground(ALTERNATE_ROW_COLOR.darker()); 
         else 
          c.setBackground(ALTERNATE_ROW_COLOR); 
        } 
       } 
       return c; 
      } 

     }; 
     table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 
     table.getTableHeader().setReorderingAllowed(false); 
     JList rowHeader = new JList(cols); 
     rowHeader.setCellRenderer(new RowHeaderRenderer(table)); 

     //Lets Place the new table in a Scroll Pane Since there could be alot of data. 
     JScrollPane scrollPane = new JScrollPane(table); 
     scrollPane.setRowHeaderView(rowHeader); 
     getContentPane().add(scrollPane, BorderLayout.CENTER); 

     //Now lets Build the Cell Editors 
     int c = 0; 
     int r = 0; 
     for(Iterator<Membership> a = _Memberships.iterator(); a.hasNext();) 
     { 
      Membership top = a.next(); 
      EachRowEditor rowEditor = new EachRowEditor(table); 
      for(Iterator<Membership> b = _Memberships.iterator(); b.hasNext();) 
      { 
       Membership side = b.next(); 

       if (side.getId() == top.getId() && (side.isEft() && top.isEft())) 
       { 
        //rowEditor.setEditorAt(r, null); 
       } 
       else if (side.getId() != top.getId() && (side.isEft() && top.isEft())) 
       { 
        NuhpadxCell t = new NuhpadxCell(side, top, new DefaultComboBoxModel(new String[] {"N", "U", "D", "A"})); 
        t.setSelectedItem(NUHPADX(side.getId(), top.getId())); 
        rowEditor.setEditorAt(r, new DefaultCellEditor(t)); 
       } 
       else 
       { 
        NuhpadxCell t = new NuhpadxCell(side, top, new DefaultComboBoxModel(new String[] {"N", "A", "H", "X", "P"})); 
        t.setSelectedItem(NUHPADX(side.getId(), top.getId())); 
        rowEditor.setEditorAt(r, new DefaultCellEditor(t)); 
       } 
       r++; 
      } 
      table.getColumn(top.getMembership()).setCellEditor(rowEditor); 
      table.revalidate(); 
      c++; 
     } 

     table.removeColumn(table.getColumn("NONE")); 

     //******************************************************* 
     // Ends Copy and paste from Program 
     //******************************************************* 
     setSize(1060, 600); 
     setVisible(true); 
    } 

    //This function jsut simluates a entire class 
    public String NUHPADX(int side, int top) 
    { 
     Random generator = new Random(); 
     int roll = generator.nextInt(7); 
     switch (roll) 
     { 
      case 0: 
       return "N"; 
      case 1: 
       return "U"; 
      case 2: 
       return "H"; 
      case 3: 
       return "P"; 
      case 4: 
       return "A"; 
      case 5: 
       return "P"; 
      case 6: 
       return "A"; 
      default: 
       return "N"; 
     } 

    } 

    public static void main(String[] args) { 
     EachRowEditorExample frame = new EachRowEditorExample(); 
     frame.addWindowListener(new WindowAdapter() { 
      public void windowClosing(WindowEvent e) { 
       System.exit(0); 
      } 
     }); 
    } 
} 

//Example from http://www.crionics.com/products/opensource/faq/swing_ex/SwingExamples.html 
/* (swing1.1.1) */ 
class EachRowEditor implements TableCellEditor { 
    protected Hashtable editors; 

    protected TableCellEditor editor, defaultEditor; 

    JTable table; 

    /** 
    * Constructs a EachRowEditor. create default editor 
    * 
    * @see TableCellEditor 
    * @see DefaultCellEditor 
    */ 
    public EachRowEditor(JTable table) { 
     this.table = table; 
     editors = new Hashtable(); 
     defaultEditor = new DefaultCellEditor(new JTextField()); 
    } 

    /** 
    * @param row 
    *   table row 
    * @param editor 
    *   table cell editor 
    */ 
    public void setEditorAt(int row, TableCellEditor editor) { 
     editors.put(new Integer(row), editor); 
    } 

    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 
     editor = (TableCellEditor) editors.get(new Integer(row)); 
     if (editor == null) { 
      editor = defaultEditor; 
     } 
     return editor.getTableCellEditorComponent(table, value, isSelected, row, column); 
    } 

    public Object getCellEditorValue() { 
     return editor.getCellEditorValue(); 
    } 

    public boolean stopCellEditing() { 
     return editor.stopCellEditing(); 
    } 

    public void cancelCellEditing() { 
     editor.cancelCellEditing(); 
    } 

    public boolean isCellEditable(EventObject anEvent) { 
     selectEditor((MouseEvent) anEvent); 
     return editor.isCellEditable(anEvent); 
    } 

    public void addCellEditorListener(CellEditorListener l) { 
     editor.addCellEditorListener(l); 
    } 

    public void removeCellEditorListener(CellEditorListener l) { 
     editor.removeCellEditorListener(l); 
    } 

    public boolean shouldSelectCell(EventObject anEvent) { 
     selectEditor((MouseEvent) anEvent); 
     return editor.shouldSelectCell(anEvent); 
    } 

    protected void selectEditor(MouseEvent e) { 
     int row; 
     if (e == null) { 
      row = table.getSelectionModel().getAnchorSelectionIndex(); 
     } else { 
      row = table.rowAtPoint(e.getPoint()); 
     } 
     editor = (TableCellEditor)editors.get(new Integer(row)); 
     if (editor == null) { 
      editor = defaultEditor; 
     } 
    } 
} 

//******************************************************* 
// Starts Copy and paste from Program 
//******************************************************* 
class RowHeaderRenderer extends JLabel implements ListCellRenderer { 
    private static final long serialVersionUID = 4619707414623897299L; 

    public RowHeaderRenderer(JTable table) { 
     JTableHeader header = table.getTableHeader(); 
     setOpaque(true); 
     setBorder(UIManager.getBorder("TableHeader.cellBorder")); 
     setHorizontalAlignment(CENTER); 
     setForeground(header.getForeground()); 
     setBackground(header.getBackground()); 
     setFont(header.getFont()); 
    } 

    @Override 
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 
     setText((value == null) ? "" : value.toString()); 
     return this; 
    } 
} 

class NuhpadxCell extends JComboBox { 
    private static final long serialVersionUID = -4464709511574911230L; 

    private Membership _side; 
    private Membership _top; 

    public NuhpadxCell(Membership s, Membership t, DefaultComboBoxModel aModel) 
    { 
     _side = s; 
     _top = t; 
     addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 
       DoUpdate(); 
      } 

     }); 

     setModel(aModel); 
    } 

    private void DoUpdate() { 
     // I would then update my database useing the ID of the side and top memberships as keys. 
    } 
} 

//******************************************************* 
// Ends Copy and paste from Program 
//******************************************************* 

//A bare Skeleton of the membership class needed to run this code. 
class Membership { 

    protected int id; 
    protected String membership; 
    protected boolean eft; 

    public int getId() { 
     return id; 
    } 
    public void setId(int value) { 
     this.id = value; 
    } 

    public String getMembership() { 
     return membership; 
    } 
    public void setMembership(String value) { 
     this.membership = value; 
    } 

    public boolean isEft() { 
     return eft; 
    } 
    public void setEft(boolean value) { 
     this.eft = value; 
    } 
} 
+0

是你的意思嗎?線程中的異常「AWT-EventQueue-0」java.lang.Nul lPointerException'from codel line'return editor.isCellEditable(anEvent);' – mKorbel

回答

2

您的解決方案描述似乎是一些看起來很簡單,非常複雜。實際上你只有兩個不同的基於JComboBox的CellEditor。

所以,一個簡單的解決方案將是一個JComboBox延長DefaultCellEditor並覆蓋getTableCellEditorComponent(),這取決於你是哪一行,你更新JComboBox與合適的模型和你回電話給super上。

最後,您在表格的所有列上設置此單元格編輯器。

也可以考慮下面的Java編碼慣例(變量和方法以小寫字母開頭,類首先是一個大寫字母,等...)

編輯:

class MyTableCellEditor extends DefaultCellEditor { 
     private DefaultCellEditor defaultEditor; 
     private DefaultComboBoxModel nudaModel = new DefaultComboBoxModel(new String[] { "N", "U", "D", "A" }); 
     private DefaultComboBoxModel nahxpModel = new DefaultComboBoxModel(new String[] { "N", "A", "H", "X", "P" }); 

     public MyTableCellEditor() { 
      super(new JComboBox()); 
      defaultEditor = new DefaultCellEditor(new JTextField()); 
     } 

     private JComboBox getComboBox() { 
      return (JComboBox) editorComponent; 
     } 

     @Override 
     public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 
      Membership top = _Memberships.get(column); 
      Membership side = _Memberships.get(row); 

      if (side.getId() == top.getId() && side.isEft() && top.isEft()) { 
       return defaultEditor.getTableCellEditorComponent(table, value, isSelected, row, column); 
      } else if (side.getId() != top.getId() && side.isEft() && top.isEft()) { 
       getComboBox().setModel(nudaModel); 
      } else { 
       getComboBox().setModel(nahxpModel); 
      } 
      return super.getTableCellEditorComponent(table, NUHPADX(side.getId(), top.getId()), isSelected, row, column); 
     } 
    } 

而且這裏是你的TableModel可能看起來如何的實現:

class MyDataModel extends AbstractTableModel{ 

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

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

     @Override 
     public String getColumnName(int column) { 
      // Here feel free to return the appropriate column names. 
      return super.getColumnName(column); 
     } 

     @Override 
     public Object getValueAt(int row, int column) { 
      return NUHPADX(_Memberships.get(row).getId(), _Memberships.get(column).getId()); 
     } 

     @Override 
     public boolean isCellEditable(int rowIndex, int columnIndex) { 
      // Here you can do whatever you want to say that is editable or not 
      // If it is editable, you need to override setValueAt 
      return true; 
     } 

     @Override 
     public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 
      // Here you need to implement the update of your model 
     } 

    } 
+0

如果你有一個例子,我願意嘗試。至於公約,我實際上有我自己的風格,我喜歡跟隨。實際上,我爲這個問題發佈了這麼多的代碼非常罕見。 – Pyromanci

+0

@ Guillaume Polet我想更好地免費使用TableModel(可以不受限制地)將隨機對象類型添加到隨機Jtables列和行 – mKorbel

+0

@Pyromanci我用示例TableCellEditor更新了我的答案,它可以替換所有的複雜的代碼和作爲獎勵,我提供了一個TableModel的實現,我相信這將更容易維護和更新。對於這些類來說,他們需要訪問(成爲這種或那種)_Membership變量(通過使其成爲final),或者通過內聯方式聲明我的兩個類,或者通過傳遞參數,或者通過使兩個類內部類使_Membership一個類變量,等等......)。對於大會,我會認真考慮切換到Java的! –

2

1.issue從代碼行來,

table.removeColumn(table.getColumn("NONE")); 

2.然後JTables view返回不同column index作爲存儲到TableModel,你必須調用在prepareRenderertable.convertColumnIndexToModel()Editor

3.從刪除isCellXxxModel ei

DataModel = new DefaultTableModel(rows, cols) { 

    @Override 
    public boolean isCellEditable(int rowIndex, int columnIndex) { 
     Object t = getValueAt(rowIndex, rowIndex); 
     if (t == null) { 
      return false; 
     } else { 
      return true; 
     } 
    } 
}; 

4.call table.setPreferredScrollableViewportSize(table.getPreferredSize());那麼你可以改變setSize(1060, 600);pack();

5.add有setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

6.don't延伸JFrame,創建一個局部變量

7那麼你的主類應該包括InitialThread

public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 

     @Override 
     public void run() { 
      EachRowEditorExample frame = new EachRowEditorExample(); 
     } 
    }); 
} 

編輯

1,我只是想隱藏的列實際上並不完全是從模型,該模型是什麼,代碼應該(根據Java文檔)做刪除。

table.removeColumn(table.getColumn("NONE")); remove concrete Column only from JTables View more in the API and JTables tutorial,這Column仍處於XxxTableModel呈現,更好的將是測試在你身邊

爲2,不知道爲什麼,真正適用。

這已經回答了,多在JTable tutorial (read the next section too)

+0

至於問題1,我只是想隱藏該列,而不是實際上完全從模型中刪除它,這就是代碼應該做的事情(根據Java Docs )。至於2,不知道爲什麼這真的適用。至於3感謝指出,似乎處理速度有點快。這不適用於所有的JFrame代碼只是爲了讓所有人都能看到可運行的代碼部分。 – Pyromanci

+0

在這裏看到我的編輯 – mKorbel

相關問題