2014-10-01 201 views
0

我在管理兩個JTable和相關數據時遇到了一些問題。JTable,TableModel和其他的複雜使用

我不得不使這個GUI: enter image description here

我解釋如何使用: 在第一個的JTable我有車輛列表(卡車,汽車...)和相對信息。 在第二個jTable中,我有一個我想讓「可用」(即sw代理啓動)的車輛列表,並按下綠色箭頭。因此,是第一個列表的子列表:在第一個表中選擇的行將在第二個列表中複製。

第一個問題: 在第一列中,我有一個說明車輛種類的圖像(您可以在示例中看到一輛卡車)。 在第三和第五列中,我有不同的jComboBoxs。參見TIPO VEICOLO(即Kind)的jComboBox:如果我選擇不同的車輛,第一列中的圖像必須更改! (如果我選擇從卡車更換爲汽車,相對圖標必須更改)。另外,我可能不想在軟件的其他地方處理這個圖標。我解釋一下:我想用

Object[] vehicle = {"aaa", "kind1", "marca", "disponibile", "ptt" } 

永不

Object[] vehicle = {"/image/truck.png" ,"aaa", "kind1", "marca", "disponibile", "ptt" } 

問題二: 在未來,我想添加JTable中其他特點:尺寸,車輛的顏色,牌照...... 我知道卡車的功能與汽車的功能不同。我想要一種方法來保持標題中的所有特徵,但是在每行中(根據車輛的種類)來激活/禁用某些單元格。

請注意:JTable中的標頭是不一定相同

package it.transfersimulation; 

import it.transfersimulation.Vehicle.Stato; 
import it.transfersimulation.Vehicle.TipoVeicolo; 

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.Toolkit; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 
import java.awt.ComponentOrientation; 

import javax.swing.DefaultCellEditor; 
import javax.swing.DefaultComboBoxModel; 
import javax.swing.ImageIcon; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.SwingUtilities; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.BoxLayout; 
import javax.swing.JTable; 
import javax.swing.event.TableModelEvent; 
import javax.swing.event.TableModelListener; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.TableColumn; 
import javax.swing.JButton; 

import java.awt.FlowLayout; 

import javax.swing.SwingConstants; 


@SuppressWarnings("serial") 
public class ShipperAgentGUI extends JFrame implements ActionListener { 

// Variabili di classe 
private JPanel masterPanel; 
private JButton btnPM_plus; 
private JButton btnPM_meno; 
private JButton btnMD_plus; 
private JButton btnMD_meno; 
private JTable availablesTable; 
private JTable parkTable; 

private Object[] parkModelHeader = { "" , "TARGA", "TIPO VEICOLO", "MARCA", "STATO", "PTT" }; 
private Object[] availablesModelHeader = { "", "TARGA", "TIPO VEICOLO", "MARCA", "STATO", "PTT" }; 

private DefaultTableModel parkModel = new DefaultTableModel(null, parkModelHeader){ 
    public Class<?> getColumnClass(int columnIndex) { 
     return getValueAt(0, columnIndex).getClass(); 
    }; 
};// per aggiungere jCheckBox, jComboBox e ImageIcon 

private DefaultTableModel availablesModel = new DefaultTableModel(null, availablesModelHeader){ 
    public Class<?> getColumnClass(int columnIndex) { 
     return getValueAt(0, columnIndex).getClass(); 
    }; 
};// per aggiungere jCheckBox, jComboBox e ImageIcon 

// My third-part software: a JADE agent: 
protected ShipperAgent shipperAgent; 

private Coordinator parkCoordinator; 
private Coordinator availablesCoordinator; 


//////////////////////////////////////////////////// 
// COSTRUTTORE 

ShipperAgentGUI(ShipperAgent agent) { 

    // Valorizza l'agente corrispondente 
    shipperAgent = agent; 


    /////////////////////////////////////////////////////////////////////// 
    // Graphics: 
    // 

    setTitle("Shipper Agent: "+agent.getLocalName()); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    try { 
     UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); 
     //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
    } catch (ClassNotFoundException | InstantiationException 
      | IllegalAccessException | UnsupportedLookAndFeelException e) { 
     e.printStackTrace(); 
    } 

    // MasterPanel 
    masterPanel = new JPanel(); 
    masterPanel.setLayout(new BoxLayout(masterPanel, BoxLayout.Y_AXIS)); 
    masterPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); 


    // Park Panel 
    JPanel parkPanel = new JPanel(); 
    parkPanel.setLayout(new BoxLayout(parkPanel, BoxLayout.Y_AXIS)); 
    masterPanel.add(parkPanel); 

    JPanel pnlHeaderParkPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); 
    JLabel parkLabel = new JLabel("Parco auto:"); 
    pnlHeaderParkPanel.add(parkLabel); 
    parkPanel.add(pnlHeaderParkPanel); 

    JPanel pnlTableParkPanel = new JPanel(); 
    pnlTableParkPanel.setLayout(new BoxLayout(pnlTableParkPanel, BoxLayout.X_AXIS)); 
    parkPanel.add(pnlTableParkPanel); 

    // Park Table 
    parkTable = new JTable(); 
    parkTable.setModel(parkModel); 
    parkTable.setPreferredScrollableViewportSize(new Dimension(500,100)); 
    parkTable.setFillsViewportHeight(true); 
    JScrollPane parkScrollPane = new JScrollPane(parkTable); 
    pnlTableParkPanel.add(parkScrollPane); 

    JPanel pnlBtnParkPanel = new JPanel(); 
    pnlTableParkPanel.add(pnlBtnParkPanel); 
    pnlBtnParkPanel.setLayout(new BoxLayout(pnlBtnParkPanel, BoxLayout.Y_AXIS)); 

    // JButtons: add/remove vehicle in Park Table 
    btnPM_plus = new JButton(); 
    btnPM_plus.setToolTipText("Aggiungi mezzo"); 
    btnPM_plus.setIcon(new ImageIcon(ShipperAgentGUI.class.getResource("/images/lorry-add.png"))); 
    btnPM_plus.setActionCommand("+parco"); 
    btnPM_plus.addActionListener(this); 
    pnlBtnParkPanel.add(btnPM_plus); 

    btnPM_meno = new JButton(); 
    btnPM_meno.setToolTipText("Rimuovi mezzo"); 
    btnPM_meno.setIcon(new ImageIcon(ShipperAgentGUI.class.getResource("/images/lorry-delete.png"))); 
    btnPM_meno.setActionCommand("-parco"); 
    btnPM_meno.addActionListener(this); 
    pnlBtnParkPanel.add(btnPM_meno); 


    // Arrow Panel 
    JPanel arrowPanel = new JPanel(); 
    masterPanel.add(arrowPanel); 

    // JButtons: available or not vehicle 
    btnMD_plus = new JButton(); 
    btnMD_plus.setToolTipText("Rendi disponibile il mezzo selezionato"); 
    btnMD_plus.setIcon(new ImageIcon(ShipperAgentGUI.class.getResource("/images/arrow-green-down.png"))); 
    arrowPanel.add(btnMD_plus); 
    btnMD_plus.setActionCommand("+disponibili"); 
    btnMD_plus.addActionListener(this); 

    btnMD_meno = new JButton(); 
    btnMD_meno.setToolTipText("Rendi indisponibile il mezzo selezionato"); 
    btnMD_meno.setIcon(new ImageIcon(ShipperAgentGUI.class.getResource("/images/arrow-red-up.png"))); 
    arrowPanel.add(btnMD_meno); 
    btnMD_meno.setActionCommand("-disponibili"); 
    btnMD_meno.addActionListener(this); 


    // Availables Panel 
    JPanel availablesPanel = new JPanel(); 
    masterPanel.add(availablesPanel); 
    availablesPanel.setLayout(new BoxLayout(availablesPanel, BoxLayout.Y_AXIS)); 

    JPanel pnlHeaderAvailablesPanel = new JPanel(); 
    FlowLayout fl_pnlHeaderAvailablesPanel = (FlowLayout) pnlHeaderAvailablesPanel.getLayout(); 
    fl_pnlHeaderAvailablesPanel.setAlignment(FlowLayout.LEFT); 
    availablesPanel.add(pnlHeaderAvailablesPanel); 
    JLabel label_1 = new JLabel("Disponibili:"); 
    pnlHeaderAvailablesPanel.add(label_1); 
    label_1.setHorizontalAlignment(SwingConstants.LEFT); 

    // Available Table 
    availablesTable = new JTable(); 
    availablesTable.setModel(availablesModel); 
    availablesTable.setPreferredScrollableViewportSize(new Dimension(500, 100)); 
    availablesTable.setFillsViewportHeight(true); 
    JScrollPane availablesScrollPane = new JScrollPane(availablesTable); 
    availablesPanel.add(availablesScrollPane); 
    getContentPane().add(masterPanel, BorderLayout.CENTER); 

    // Search Panel 
    JPanel searchPanel = new JPanel(); 
    masterPanel.add(searchPanel); 
    JButton btnSearch = new JButton("Search"); 
    searchPanel.add(btnSearch); 

    // End of graphics init 
    /////////////////////////////////// 


    ////////////////////////////////////// 
    // Editor delle colonne delle tabelle 
    // TODO 
    JComboBox<TipoVeicolo> tipoVeicoloComboBox = new JComboBox<TipoVeicolo>(); 
    tipoVeicoloComboBox.setModel(new DefaultComboBoxModel<TipoVeicolo>(TipoVeicolo.values())); 
    JComboBox<Stato> statoComboBox = new JComboBox<Stato>(); 
    statoComboBox.setModel(new DefaultComboBoxModel<Stato>(Stato.values())); 

    TableColumn tipoVeicoloColumn = parkTable.getColumnModel().getColumn(2); 
    TableColumn statoColumn = parkTable.getColumnModel().getColumn(4); 

    tipoVeicoloColumn.setCellEditor(new DefaultCellEditor(tipoVeicoloComboBox)); 
    statoColumn.setCellEditor(new DefaultCellEditor(statoComboBox)); 


    ///////////////////////////////////////////////////////////////////// 
    // Coordinators (ispirati al Mediator pattern) 

    parkCoordinator = new Coordinator(shipperAgent, parkModel) { 
     @Override 
     public void notifyAndAddRow(final Object[] rowData) { 
      shipperAgent.newTruck((String) rowData[0]); 

      SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        tableModel.addRow(rowData); 
       } 
      }); 
     } 

     @Override 
     public void notifyAndDeleteRow(final int rowIndex) { 
      final String truck = (String)this.tableModel.getValueAt(rowIndex, 0); 
      int flag=search(availablesCoordinator.tableModel, truck); 
      if (flag!=-1) 
       removeVehicle(availablesCoordinator, flag); 
      shipperAgent.removeTruck(truck); 

      SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        tableModel.removeRow(rowIndex); 
       } 
      }); 
     } 
    }; 


    availablesCoordinator = new Coordinator(shipperAgent, availablesModel) { 
     @Override 
     public void notifyAndAddRow(final Object[] rowData) { 
      shipperAgent.activateTruck((String) rowData[0]); 

      SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        tableModel.addRow(rowData); 
       } 
      }); 
     } 

     @Override 
     public void notifyAndDeleteRow(final int rowIndex) { 
      String truck = (String)this.tableModel.getValueAt(rowIndex, 1); 
      shipperAgent.deactivateTruck(truck); 

      SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        tableModel.removeRow(rowIndex); 
       } 
      }); 
     } 
    }; 


    ///////////////////////////////////////////////////// 
    // Listeners: 

    parkModel.addTableModelListener(parcoListener); 
    availablesModel.addTableModelListener(mezziDisponibiliListener); 


    ///////////////////////////////////////////////////// 
    // Contatto con l'agente - Riempimento dati 
    // TODO 
    Object[] veicoli = shipperAgent.getVehicles(); 
    for (int i=0; i<veicoli.length;i++){ 
     Object[] info = (Object[]) veicoli[i]; 
     Object[] veicolo = new Object[info.length+1]; 

     veicolo[0] = new ImageIcon(ShipperAgentGUI.class.getResource("/images/lorry-icon.png")); 

     for (int j=1;j<info.length+1;j++){ 
      veicolo[j]=info[j-1]; 
     } 

     parkModel.addRow(veicolo); 

     if (veicolo[4] == Stato.DISPONIBILE) 
      availablesModel.addRow(veicolo); 
    } 

    //////////////////////////// 
    // Show GUI 
    showGui(); 
} 


public void showGui() { 
    pack(); 
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
    int centerX = (int) screenSize.getWidth()/2; 
    int centerY = (int) screenSize.getHeight()/2; 
    setLocation(centerX - getWidth()/2, centerY - getHeight()/2); 
    super.setVisible(true); 
} 


////////////////////////////////////////////// 
// actionPerformed 

@Override 
public void actionPerformed(ActionEvent e) { 
    switch (e.getActionCommand()) { 
    case "+parco": { 
     new VehicleInsertJDialog(this, parkCoordinator); 
    } break; 

    case "-parco": { 
     int selectedRow = parkTable.getSelectedRow(); 
     if (selectedRow != -1) 
      removeVehicle(parkCoordinator, selectedRow); 
    } break; 

    case "+disponibili": { 
     int selectedRow = parkTable.getSelectedRow(); 
     if (selectedRow != -1){ 
      //TODO controlla la consistenza 
      addVehicle(availablesCoordinator, 
        String.valueOf(parkModel.getValueAt(selectedRow, 0)), 
        String.valueOf(parkModel.getValueAt(selectedRow, 1)), 
        String.valueOf(parkModel.getValueAt(selectedRow, 2)), 
        String.valueOf(parkModel.getValueAt(selectedRow, 3)), 
        String.valueOf(parkModel.getValueAt(selectedRow, 4)) 
        ); 

     } 
    } break; 

    case "-disponibili": { 
     int selectedRow = availablesTable.getSelectedRow(); 
     if (selectedRow != -1) 
      removeVehicle(availablesCoordinator, selectedRow); 
    } break; 

    default: 
     System.out.println("Imprevisto in actionPerformed()"); 
     break; 
    } 
} 



// ///////////////////////////////////// 
// Add/Remove vehicles methods 

public void addVehicle(Coordinator coordinator, 
     String targa, String tipo, String marca, String stato, String peso) { 
    coordinator.notifyAndAddRow(new Object[]{targa, tipo, marca, stato, peso}); 
} 

public void removeVehicle(Coordinator coordinator, int index) { 
    coordinator.notifyAndDeleteRow(index); 
} 


// ////////////////////////////////////////// 
// LISTENER: 

TableModelListener parcoListener = new TableModelListener() { 
    public void tableChanged(TableModelEvent e) { 
     switch (e.getType()) { 
     case (TableModelEvent.INSERT): 
      System.out.println("un inserimento in corso!"); break; 
     case (TableModelEvent.DELETE): 
      System.out.println("una cancellazione in corso!"); break; 
     case (TableModelEvent.UPDATE): 
      System.out.println("un aggiornamento in corso!"); break; 
     } 
    } 
}; 

TableModelListener mezziDisponibiliListener = new TableModelListener() { 
    public void tableChanged(TableModelEvent e) { 
     switch (e.getType()) { 
     case (TableModelEvent.INSERT): 
      System.out.println("un inserimento in corso!"); break; 
     case (TableModelEvent.DELETE): 
      System.out.println("una cancellazione in corso!"); break; 
     case (TableModelEvent.UPDATE): 
      System.out.println("un aggiornamento in corso!"); break; 
     } 
    } 
}; 



private int search(DefaultTableModel tableModel, String targa) { 
    int flag = -1; 
    for (int i=0; i<tableModel.getRowCount(); i++) 
     if (tableModel.getValueAt(i, 0).equals(targa)) 
      flag=i; 
    return flag; 
} 






/////////////////////////////////////// 
// INNER CLASS 
/////////////////////////////////////// 

protected abstract class Coordinator { 

    /* 
    * protected class members so subclasses can access these directly 
    */ 

    protected ShipperAgent shipperAgent; 
    protected DefaultTableModel tableModel; 

    public Coordinator(ShipperAgent sa, DefaultTableModel tm) { 
     shipperAgent = sa; 
     tableModel = tm; 
    } 

    public abstract void notifyAndAddRow(Object[] rowData); 

    public abstract void notifyAndDeleteRow(int rowIndex); 
} 

} 
+1

我不能在第一個問題或第二個問題 – 2014-10-01 14:04:58

+0

中發現具體問題,如果不清楚,對不起。對於第一個問題,我想知道在jTable中使用圖標的方法,但不要像處理信息的一部分那樣處理圖標。我希望jTable能夠自己實現這種車輛並改變連貫性的圖標。我在哪裏可以做到這一點? – Gioce90 2014-10-01 14:15:36

回答

2

我明白,我的第一個實施不利於我的exigence。 首先,DefaultTableModel的使用是一個很大的限制,因爲你只能使用Vector,Object,String ... 在我的情況下,我想通過jtable操縱一組車輛。所以,第一件事:

Vehicle.java

public class Vehicle { 

    enum TipoVeicolo { 
     AUTO, FURGONE, 
     AUTOCARRO, 
     AUTOARTICOLATO 
    }; 

    private String targa; 
    private TipoVeicolo tipoVeicolo; 
    private String marca; 
    private Stato stato 
    private float ptt; 
    //... others... 

    // constructor 
    public Vehicle(String targa, TipoVeicolo tipoVeicolo, String marca, Stato stato, float ptt) { 
     this.targa=targa; 
     this.tipoVeicolo=tipoVeicolo; 
     // ... bla bla 
    } 

    // GET and SET methods... 
    //... 
} 

現在,我已經做到了這一點。新的是擴展AbstractTableModel上(而不是的DefaultTableModel)類

VehicleTableModel.java

public class VehicleTableModel extends AbstractTableModel { 

    // private objects 
    private ArrayList<Vehicle> vehicles; 
    private COLUMNS[] header; 

    // possible column names: 
    public enum COLUMNS { 
     IMAGE_COLUMN, 
     TARGA_COLUMN, 
     CAR_TYPE_COLUMN, 
     //... 
    }; // if I want I can add others... 



    /////////////////////////////////////////////////////// 
    // Constructor: 

    public VehicleTableModel(COLUMNS[] headerTable) { 
     this.vehicles = new ArrayList<Vehicle>() 
     this.header = headerTable; 
    } 


    /////////////////////////////////////////////////////// 
    // obligatory override methods (from AbstractTableModel): 

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

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

    // this works! :D 
    @Override 
    public Object getValueAt(int row, int col) { 
     Object value = "?"; 
     Vehicle v = vehicles.get(row); 
     if (v!=null) { 
      COLUMNS column = header[col]; 
      switch (column) { 
       case IMAGE_COLUMN: 
        int i = findColumn(COLUMNS.CAR_TYPE_COLUMN); // find the right column index 
        Object tipo = getValueAt(row, i); 
        value = (ImageIcon)findImageByColumnCarType(tipo); // find the right icon for the type of vehicle. 
        break; 
       case TARGA_COLUMN: 
        value = v.getTarga(); 
        break; 
       case CAR_TYPE_COLUMN: 
        value = v.getTipoVeicolo(); 
        break; 
       //... 
      } 
     } 
     return value; 
    } 



    /////////////////////////////////////////////////////// 
    // My methods: 

    public void addRow(Vehicle vehicle) { 
     if (!vehicles.contains(vehicle)){ 
      vehicles.add(vehicle); 
      fireTableRowsInserted(0, getRowCount()); // I'm not so sure of this.. 
    } 

    /* I'm not so sure of this.. 
    public boolean removeRow(Vehicle vehicle) { 
     boolean flag = vehicles.remove(vehicle); 
     fireTableRowsDeleted(0, getRowCount()); // or fireTableDataChanged(); ? 
     return flag; 
    }*/ 

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


    public Vehicle getVehicleAt(int row) { 
     return vehicles.get(row); 
    } 

    // found the corresponding column index 
    public int findColumn(COLUMNS columnName) { 
     for (int i=0; i<getColumnCount(); i++) 
      if (columnName.equals(header[i])) 
       return i; 
     return -1; 
    } 

    // found the right image 
    protected static ImageIcon findImageByColumnCarType(Object value) { 
     ImageIcon i = null; 
     if (value.equals(TipoVeicolo.AUTO)) 
      i = new ImageIcon(VehicleTableModel.class.getResource("/images/Car-icon_32.png")); 
     else if (value.equals(TipoVeicolo.AUTOARTICOLATO)) 
      i = new ImageIcon(VehicleTableModel.class.getResource("/images/City-Truck-blue-icon_32.png")); 
     //... 
     return i; 
    } 

    // knows if exist a value (of a column) in all rows 
    private boolean controllIfExist(Object value, int col) { 
     boolean bool = false; 
     for (int i=0; i<getRowCount();i++){ 
      if (value.equals(getValueAt(i, col))){ 
       bool=true; 
       break; 
      } 
     } 
     return bool; 
    } 



    /////////////////////////////////////////////////////// 
    // other methods (from AbstractTableModel) to ovveride: 

    // this works! :D 
    @Override 
    public Class<?> getColumnClass(int col) { 
     Class<?> c; 
     COLUMNS column = header[col]; 
     if (column.equals(COLUMNS.IMAGE_COLUMN)) 
      c = ImageIcon.class; 
     else if (column.equals(COLUMNS.CAR_TYPE_COLUMN)) 
      c = JComboBox.class; 
     // else if blabla.... 
     else c = super.getColumnClass(col); 
     return c; 
    } 

    // this works! :D 
    @Override 
    public String getColumnName(int col) { 
     COLUMNS column = header[col]; 
     if (column.equals(COLUMNS.IMAGE_COLUMN)) 
      return " "; 
     else if (column.equals(COLUMNS.TARGA_COLUMN)) 
      return "Targa"; 
     else if (column.equals(COLUMNS.CAR_TYPE_COLUMN)) 
      return "Tipo veicolo"; 
     // else if blabla... 
     return super.getColumnName(col); 
    }; 


    @Override 
    public boolean isCellEditable(int row, int col) { 
     return true; 
    } 


    @Override 
    public void setValueAt(Object value, int row, int col) { 
     Vehicle v = vehicles.get(row); 
     boolean flag = false; 
     if (v!=null) { 
      COLUMNS column = header[col]; 
      switch (column) { 
       case TARGA_COLUMN: 
        if (!v.getTarga().equals(value)){ 
         if (!controllIfExist(value, col)){ 
          v.setTarga((String) value); 
          flag = true; 
         } 
        } 
        break; 
       case CAR_TYPE_COLUMN: 
        if (!v.getTipoVeicolo().equals(value)){ 
         v.setTipoVeicolo((TipoVeicolo) value); 
         flag = true; 
        } 
        break; 
       // other cases bla bla... 
      } 

      if (flag) // update only if have found modify 
       fireTableRowsUpdated(0, getRowCount()); // or fireTableRowsUpdated(row, row); ? 
     } 
    } 

} 

在此之後,對商品,我創建了一個VehicleTable(擴展的JTable)。它可以像沒用,但適合我的目標......你可以看到特殊的細胞正確的設置(與JComboBox的細胞,例如)

VehicleTable.java

public class VehicleTable extends JTable { 

public VehicleTable(VehicleTableModel vehicleModel) { 
    super(vehicleModel); 
    this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
    this.setColumnSelectionAllowed(false); 
    this.setCellSelectionEnabled(false); 
    this.setRowSelectionAllowed(true); 
    this.setShowHorizontalLines(true); 
    this.setRowHeight(25); 
    this.setPreferredScrollableViewportSize(new Dimension(700,150)); 
    this.setFillsViewportHeight(true); 

    //////////////////////////////////// 
    // Now I set the columns features: 
    int flag=-1; 
    TableColumn column; 

    // Icon Column: 
    flag = vehicleModel.findColumn(COLUMNS.IMAGE_COLUMN); 
    if (flag!=-1){ 
     column = this.getColumnModel().getColumn(flag); 
     column.setMinWidth(80); 
     column.setMaxWidth(80); 
    } 

    // Targa Column: 
    flag = vehicleModel.findColumn(COLUMNS.TARGA_COLUMN); 
    if (flag!=-1){ 
     column = this.getColumnModel().getColumn(flag); 
     column.setMinWidth(100); 
     column.setMaxWidth(100); 
    } 

    // Tipo veicolo Column 
    flag = vehicleModel.findColumn(COLUMNS.CAR_TYPE_COLUMN); 
    if (flag!=-1){ 
     column = this.getColumnModel().getColumn(flag); 
     column.setCellEditor(new DefaultCellEditor(
       new JComboBox<TipoVeicolo>(TipoVeicolo.values()))); 
     column.setMinWidth(150); 
     column.setMaxWidth(150); 
    } 

    //others... 
} 

最後,我們可以使用這個。例如,在我的GUI

ShipperAgentGUI.java(摘錄我專注於一個表)

public class ShipperAgentGUI extends JFrame implements ActionListener { 

    // ... bla bla 

    private COLUMNS[] parkModelHeader = {COLUMNS.IMAGE_COLUMN, COLUMNS.TARGA_COLUMN, 
     COLUMNS.CAR_TYPE_COLUMN, COLUMNS.MARCA_COLUMN, COLUMNS.STATE_COLUMN, COLUMNS.PTT_COLUMN }; 
    private VehicleTableModel parkModel = new VehicleTableModel(parkModelHeader); 
    private VehicleTable parkTable; 
    private Coordinator parkCoordinator; // long story 

    protected ShipperAgent shipperAgent; // my agent, my third-part software 

    // ... bla bla 

    // Constructor: 
    ShipperAgentGUI(ShipperAgent agent) { 

     //... bla bla 

     // Park Table: 
     parkTable = new VehicleTable(parkModel); 
     JScrollPane parkScrollPane = new JScrollPane(parkTable); 
     pnlTableParkPanel.add(parkScrollPane); 

     //... bla bla 

     // Coordinators (Mediator pattern's ispired) 
     // Long story. Is for coordinating with my agent and others tables in my GUI 
     parkCoordinator = new Coordinator(shipperAgent, parkModel) { 

      @Override 
      public void notifyAndAddRow(final Vehicle vehicle) { 
       shipperAgent.newTruck(vehicle.getTarga()); // comunicate with the agent 

       SwingUtilities.invokeLater(new Runnable() { 
        @Override 
        public void run() { 
         parkModel.addRow(vehicle); 
        } 
       }); 
      } 

      @Override 
      public void notifyAndDeleteRow(final int rowIndex) { 
       final Vehicle v = this.tableModel.getVehicleAt(rowIndex); 
       // bla bla 
       shipperAgent.removeTruck(v.getTarga()); // comunicate with the agent 

       SwingUtilities.invokeLater(new Runnable() { 
        @Override 
        public void run() { 
         //parkModel.removeRow(v); 
         parkModel.removeRow(rowIndex); 
        } 
       }); 
      } 
@Override 
public void notifyRowUpdated() { 
    parkModel.addTableModelListener(new TableModelListener() { 
     public void tableChanged(TableModelEvent e) { 
      switch (e.getType()) { 
       case (TableModelEvent.DELETE): 
        parkTable.repaint(); 
        break; 
       case (TableModelEvent.UPDATE): 
        int row = e.getLastRow(); 
        int col = parkModel.getIndexColumn(COLUMNS.STATE_COLUMN); 
        if (parkModel.getValueAt(row, col).equals(Stato.DISPONIBILE)) 
         addVehicle(availablesCoordinator, parkModel.getVehicleAt(row)); 
        else 
         //removeVehicle(availablesCoordinator, row); error! 
         availablesModel.removeRow(parkModel.getVehicleAt(row)); 
        repaint(); 
        break; 
      } 
     } 
    }); 
} 
     }; 


     ArrayList<Vehicle> veicoli = shipperAgent.getVehicles(); // from agent 
     Iterator<Vehicle> I = veicoli.iterator(); 
     while (I.hasNext()){ 
      addVehicle(parkCoordinator, I.next()); 
     } 

     //... bla bla 

    } // end of constructor 

    // ... others methods... 

    private void addVehicle(Coordinator coordinator, Vehicle v) { 
     coordinator.notifyAndAddRow(v); 
    } 

    public void removeVehicle(Coordinator coordinator, int index) { 
     coordinator.notifyAndDeleteRow(index); 
    } 

    // ... 

} 

你可以看到結果這裏:

enter image description here

我還需要定義一些事情,但它應該是正確的方式。

+1

+1但我只是將圖像緩存在「Map」中。 'getValueAt'被相當頻繁地調用。所以不斷地做IO是浪費資源 – 2014-10-14 09:36:47

+0

@peeskillet是的,我明白你的觀點......在不久的將來我會這樣做。謝謝 – Gioce90 2014-10-15 09:37:59

2

「我想知道使用的方法在JTable中的圖標,但不希望處理這樣的一個部分圖標。信息我想的是,JTable中通過自身實現車輛的種類,改變conseguency的圖標」

你將有一個非常艱難的時間試圖與該做到這一點:

Object[] vehicle = {"aaa", "kind1", "marca", "disponibile", "ptt" }; 

更好地使用另一個圖像列的值。請記住,你可以有空值。第一

第一件事,這樣的:

Object[] vehicle = {"/image/truck.png" ,"aaa", "kind1", 
        "marca", "disponibile", "ptt" }; 

可以在此

Object[] vehicle = {new ImageIcon(...) ,"aaa", "kind1", 
        "marca", "disponibile", "ptt" } 

因爲,你已經覆蓋getColumnClass(),默認渲染器將渲染列的圖像,作爲ImageIcon.class會檢測。見How to use Tables: Editors and Renderers

至於主要問題,如何根據車輛變化的種類動態改變圖像,可以覆蓋表模型的setValueAt。像

DefaultTableModel model = new DefaultTableModel(...) { 
    private static final int CAR_TYPE_COLUMN = 2; 
    private static final int IMAGE_COLUMN = 0; 

    @Override 
    public void setValueAt(Object value, int row, int col) { 
     if (col == CAR_TYPE_COLUMN) { 
      ImageIcon icon = findImageByColumnCarType(value); 
      super.setValueAt(icon, row, IMAGE_COLUMN); 
     } 
     super.setValueAt(value, row, col); 
    } 

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

哪裏findImageByColumnCarType事情是找到基礎上valueImageIcon一些方法。編輯器會調用setValueAt,在您的情況下是組合框。因此,當設置值時,組合框的值將傳遞到setValueAt,您可以使用它調用方法findImageByColumnCarType以獲取ImageIcon。您可以使用Map或您用來保存圖標和相應值的東西。你可以有一個沒有圖像

一個車種的方法返回null一旦你的ImageIcon你想要的,它只是調用super.setValueAt設置新的圖標爲同一行中的圖像列的問題。

+0

是一個很好的答案。但是我有一個問題...在這個** setValueAt **的實現中,我們有兩次更新** TableModelListener **。是不可能減少的? – Gioce90 2014-10-05 17:36:58

+0

**應該用'setValueAt'完成。兩個表+兩個表模型==兩個'setValueAt' – 2014-10-05 19:48:26

+0

如果你想創建一個擴展'DefaultTableModel'的類,那麼你可以使用該類的兩個實例。這樣你只需要做一次。你正在使用兩個_anonymous_類,所以你需要做兩次。 – 2014-10-05 19:54:02

相關問題