2012-11-05 79 views
1

我是GUI界面設計的新手,我試圖在我走得太遠之前計劃出錯方法,任何幫助都不錯。我試圖顯示JTableEmployee,其本身具有StringArrayList<Cert>的數據類型。 Cert包含String使用帶自定義渲染器的JComboBox作爲JTable單元格渲染器/編輯器(架構)

我想讓表格顯示數據進行編輯,但對於一些列我想實現一個JComboBox從一組有效字符串中選擇String,以及每個顏色選項不同(JComboBox中的不同背景顏色)。

此外,ArrayList<Cert>當前在單元格中顯示爲[xxx,xxx,...],其中XXX是中每個項目的toString()函數的返回值。我想我想將ArrayList<Cert>顯示爲只讀JComboBox,但我不太關心這個項目。

我在問我需要創建多少個類才能實現此目的。我已經爲JTable延伸AbstractTableModel自定義模型。我是否需要編寫JComboBox的擴展名,還是隻需要將JComboBox的合適渲染器作爲單元格擴展並在那裏執行魔術,然後將該自定義渲染器分配給String單元格的單元格渲染器?

這是我到目前爲止,輕輕刪節:

public class EmployeeTableModel extends AbstractTableModel { 
    ... 
    private ArrayList<Employee> myDataObjects = new ArrayList<Employee>(); 
    ... 
    @Override 
    public Object getValueAt(int row, int column) { 
     Employee emp = myDataObjects.get(row); 

     switch (column) { 
      case 0: 
       return emp.getName(); 
      case 1: 
       return emp.getShift(); 
      case 2: 
       return emp.getCertifications(); 
      default: 
       return ""; 
     } 
    } 
} 

員工:

public class Employee { 
    private String name; 
    private String shift; 
    private ArrayList<Cert> certs; 
    ... 
    public String getName() { 
    return name; 
    } 

    public String getShift() { 
    return shift; 
    } 

    public ArrayList<Cert> getCerts() { 
    return certs; 
    } 
    ... 
}  

而且初始化:

EmployeeTableModel etm = new EmployeeTableModel(); 
JTable employeeTable = new JTable(); 
employeeTable.setModel(etm); 
+0

[這是](http://stackoverflow.com/questions/12107545/12108024#12108024) –

+0

使用'DefaultCellEditor看到這個[示例](http://stackoverflow.com/a/7356518/230513) '。 – trashgod

回答

4

就可以下手,最簡單的代碼是可能的,也許取決於如果你想看到JComboBox as Renderer too by @aterai

import java.awt.BorderLayout; 
import javax.swing.DefaultCellEditor; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.table.AbstractTableModel; 
import javax.swing.table.DefaultTableCellRenderer; 
import javax.swing.table.TableCellRenderer; 
import javax.swing.table.TableColumn; 
import java.awt.Component; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.ArrayList; 
import javax.swing.JButton; 
import javax.swing.JComboBox; 
import javax.swing.JList; 
import javax.swing.plaf.basic.BasicComboBoxRenderer; 

public class TableRenderDemo extends JPanel { 

    private static final long serialVersionUID = 1L; 

    public TableRenderDemo() { 
     super(new BorderLayout(5, 5)); 
     final JTable table = new JTable(new MyTableModel()); 
     table.setPreferredScrollableViewportSize(table.getPreferredSize()); 
     table.setFillsViewportHeight(true); 
     table.setRowHeight(20); 
     JScrollPane scrollPane = new JScrollPane(table); 
     initColumnSizes(table); 
     setUpSportColumn(table, table.getColumnModel().getColumn(2)); 
     add(scrollPane, BorderLayout.CENTER); 
     JButton resetButton = new JButton("Reset to default"); 
     resetButton.addActionListener(new ActionListener() { 

      public void actionPerformed(ActionEvent e) { 
       for (int i = 0; i < table.getRowCount(); i++) { 
        table.getModel().setValueAt("None of the above", i, 2); 
       } 
      } 
     }); 
     add(resetButton, BorderLayout.SOUTH); 
    } 

    private void initColumnSizes(JTable table) { 
     MyTableModel model = (MyTableModel) table.getModel(); 
     TableColumn column = null; 
     Component comp = null; 
     int headerWidth = 0; 
     int cellWidth = 0; 
     Object[] longValues = model.longValues; 
     TableCellRenderer headerRenderer = table.getTableHeader().getDefaultRenderer(); 
     for (int i = 0; i < 5; i++) { 
      column = table.getColumnModel().getColumn(i); 
      comp = headerRenderer.getTableCellRendererComponent(null, column.getHeaderValue(), false, false, 0, 0); 
      headerWidth = comp.getPreferredSize().width; 
      comp = table.getDefaultRenderer(model.getColumnClass(i)).getTableCellRendererComponent(table, longValues[i], false, false, 0, i); 
      cellWidth = comp.getPreferredSize().width; 
      column.setPreferredWidth(Math.max(headerWidth, cellWidth)); 
     } 
    } 

    private void setUpSportColumn(JTable table, TableColumn sportColumn) { 
     ArrayList<String> listSomeString = new ArrayList<String>(); 
     listSomeString.add("Snowboarding"); 
     listSomeString.add("Rowing"); 
     listSomeString.add("Knitting"); 
     listSomeString.add("Speed reading"); 
     listSomeString.add("Pool"); 
     listSomeString.add("None of the above"); 
     JComboBox comboBox = new JComboBox(); 
     comboBox.addItem(new Item(1, "-")); 
     comboBox.addItem(new Item(2, "Snowboarding")); 
     comboBox.addItem(new Item(3, "Rowing")); 
     comboBox.addItem(new Item(4, "Knitting")); 
     comboBox.addItem(new Item(5, "Speed reading")); 
     comboBox.addItem(new Item(6, "Pool")); 
     comboBox.addItem(new Item(7, "None of the above")); 
     comboBox.setMaximumRowCount(3); 
     comboBox.addActionListener(new ActionListener() { 

      public void actionPerformed(ActionEvent e) { 
       JComboBox comboBox = (JComboBox) e.getSource(); 
       Item item = (Item) comboBox.getSelectedItem(); 
       System.out.println(item.getId() + " : " + item.getDescription()); 
      } 
     }); 
     comboBox.setRenderer(new ItemRenderer()); 
     sportColumn.setCellEditor(new DefaultCellEditor(comboBox)); 
     DefaultTableCellRenderer renderer = new DefaultTableCellRenderer(); 
     renderer.setToolTipText("Click for combo box"); 
     sportColumn.setCellRenderer(renderer); 
    } 

    class ItemRenderer extends BasicComboBoxRenderer { 

     @Override 
     public Component getListCellRendererComponent(JList list, Object value, 
       int index, boolean isSelected, boolean cellHasFocus) { 
      super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 
      if (value != null) { 
       Item item = (Item) value; 
       setText(item.getDescription().toUpperCase()); 
      } 
      if (index == -1) { 
       Item item = (Item) value; 
       setText("" + item.getId()); 
      } 
      return this; 
     } 
    } 

    class Item { 

     private int id; 
     private String description; 

     public Item(int id, String description) { 
      this.id = id; 
      this.description = description; 
     } 

     public int getId() { 
      return id; 
     } 

     public String getDescription() { 
      return description; 
     } 

     @Override 
     public String toString() { 
      return description; 
     } 
    } 

    class MyTableModel extends AbstractTableModel { 

     private static final long serialVersionUID = 1L; 
     private String[] columnNames = {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian"}; 
     private Object[][] data = {{"Kathy", "Smith", "Snowboarding", new Integer(5), false}, 
      {"John", "Doe", "Rowing", new Integer(3), true}, {"Sue", "Black", "Knitting", new Integer(2), false}, 
      {"Jane", "White", "Speed reading", new Integer(20), true}, {"Joe", "Brown", "Pool", new Integer(10), false}}; 
     public final Object[] longValues = {"Jane", "Kathy", "None of the above", new Integer(20), Boolean.TRUE}; 

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

     @Override 
     public int getRowCount() { 
      return data.length; 
     } 

     @Override 
     public String getColumnName(int col) { 
      return columnNames[col]; 
     } 

     @Override 
     public Object getValueAt(int row, int col) { 
      return data[row][col]; 
     } 

     @Override 
     public Class<?> getColumnClass(int c) { 
      return getValueAt(0, c).getClass(); 
     } 

     @Override 
     public boolean isCellEditable(int row, int col) { 
      if (col < 2) { 
       return false; 
      } else { 
       return true; 
      } 
     } 

     @Override 
     public void setValueAt(Object value, int row, int col) { 
      data[row][col] = value; 
      fireTableCellUpdated(row, col); 
      System.out.println("New value of data: " + getValueAt(row, col)); 
     } 
    } 

    private static void createAndShowGUI() { 
     JFrame frame = new JFrame("TableRenderDemo"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     TableRenderDemo newContentPane = new TableRenderDemo(); 
     frame.setContentPane(newContentPane); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

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

      @Override 
      public void run() { 
       createAndShowGUI(); 
      } 
     }); 
    } 
} 
+0

這清理了很多我的困惑。我想我只會擴展'JComboBox',併爲每種類型的'String'使用帶有'HashMap'風格的內部'Renderer'。 – Sam