复杂使用JTable,TableModel等

时间:2014-10-01 13:47:38

标签: java swing jtable tablemodel defaulttablemodel

我在管理两个JTable和相关数据时遇到了一些问题。

我做了这个GUI: enter image description here

我解释一下用法: 在第一个jTable中,我列出了车辆(卡车,汽车......)和相关信息。 在第二个jTable中,我有一个我希望“可用”(即sw代理启动)的车辆列表,按下绿色箭头。因此,是第一个列表的子列表:第一个表中选择的行将复制到第二个列表中。

第一个问题: 在第一列中,我有一个车辆类型的解释图像(您可以在示例中看到一辆卡车)。 在第三和第五列中,我有不同的jComboBox。请参阅TIPO VEICOLO的jComboBox(即Kind):如果我选择不同的车辆,则第一列中的Image必须更改! (如果我选择从卡车改为卡车,相关的图标必须更改)。 此外,我可能不希望在软件的其他地方处理此图标。我解释一下:我想用

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

永远不会

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

第二个问题: 将来我想在jTable中添加其他功能:尺寸,车辆颜色,许可证...... 我知道卡车的功能与汽车的功能不同。我想要一种方法来保持标题中的所有功能,但是在每一行(根据车辆类型)激活/禁用某些单元格。

请注意:jTables的标题不一定相同

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);
}

}

2 个答案:

答案 0 :(得分:2)

  

&#34;我想知道一种在jTable中使用Icon的方法,但是DON&T要想像处理信息的一部分一样处理图标。我希望jTable能够自己实现这种车辆并改变连续性的图标&#34;

你真的很难用这个来做这件事:

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是根据ImageIcon找到value的方法。编辑器将调用setValueAt,在您的情况下为组合框。因此,在设置值时,组合框的值将传递给setValueAt,您可以使用它来调用方法findImageByColumnCarType以获取ImageIcon。您可以使用Map或其他东西来保存图标和相应的值。对于没有图像的汽车类型,您可以使用方法返回null

获得所需的ImageIcon后,只需调用super.setValueAt为同一行的图像列设置新图标即可。

答案 1 :(得分:2)

我明白我的第一次实施对我的好处并不好。 首先,使用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...
    //...
}

现在,我已经这样做了。 new是扩展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

我仍然需要定义一些东西,但它应该是正确的方法。