Complex use of JTable, TableModel and others

后端 未结 2 2037
别跟我提以往
别跟我提以往 2021-01-17 06:33

I have some problems with the manage of two JTable, and relative data.

I had make this GUI: \"enter

2条回答
  •  忘掉有多难
    2021-01-17 06:47

    I have understand that my first implementation isn't good for my exigence. First things first, the using of DefaultTableModel is a great limitation, because you can use only Vector, Object, String... In my case, I want manipulate by jtable a set of Vehicles. So, the first things:

    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...
        //...
    }
    

    Now, I had already done this. The new is the class that extends AbstractTableModel (and not DefaultTableModel)

    VehicleTableModel.java

    public class VehicleTableModel extends AbstractTableModel {
    
        // private objects
        private ArrayList 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()
            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 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); ?
            }
        }
    
    }
    

    After this, for commodity, I create a VehicleTable (extends JTable). Can it look like useless, but is right for my objective... You can see the right settings for the special cells (cell with JComboBox, for example)

    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.values())));
            column.setMinWidth(150);
            column.setMaxWidth(150);
        }
    
        //others...
    }
    

    Finally, we can use this. For example in my GUI

    ShipperAgentGUI.java (an extract. I focus on ONE table)

    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 veicoli = shipperAgent.getVehicles(); // from agent
            Iterator 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);
        }
    
        // ...
    
    }
    

    You can see the results here:

    enter image description here

    I still need to define a couple of things, but it should be the right way.

提交回复
热议问题