问题
I have some problems with the manage of two JTable, and relative data.
I had make this GUI:
I explain the use: In the first jTable I have a list of vehicles (trucks, cars...) and relative info. In the second jTable I have a list of vehicles that I want make "available" (i.e. a sw agent starts), with the press of the green arrow. So, is a sublist of the first list: the row selected in the first table are copied in the second.
First problem: In the first column I have a explicative image of the kind of vehicle (you can see a truck in the example). In the third and fifth column I have different jComboBoxs. See the jComboBox of TIPO VEICOLO (i.e. Kind): if I choose a different vehicle the Image in the first column must change! (if I choose to change from Truck to Car, the relative Icon must change). Moreover, possibily, I don't want handle this icon in other places in the software. I explain: I want use
Object[] vehicle = {"aaa", "kind1", "marca", "disponibile", "ptt" }
and never
Object[] vehicle = {"/image/truck.png" ,"aaa", "kind1", "marca", "disponibile", "ptt" }
Second problem: In the future I want add other features in the jTable: dimensions, vehicle's color, licence... I know that the features for a truck are different from features for a car. I want a way for keep all features in the header, but in every row (according the kind of vehicle) to activate/disable some cells.
Please note: The headers of jTables are not necessarily the same
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:
"I want know a way for use a Icon in jTable but DON'T want handle the icon like a part of the informations. I want that the jTable realizes by itself the kind of vehicle and change the icon of conseguency"
You're going to have a really tough time trying to do it with this:
Object[] vehicle = {"aaa", "kind1", "marca", "disponibile", "ptt" };
Better to use the other one, with the value for the image columns. Remember, you can have null values.
First things first, this:
Object[] vehicle = {"/image/truck.png" ,"aaa", "kind1",
"marca", "disponibile", "ptt" };
Can be this
Object[] vehicle = {new ImageIcon(...) ,"aaa", "kind1",
"marca", "disponibile", "ptt" }
Since, you've overridden getColumnClass()
, the default renderer will render the column as an image, as ImageIcon.class
will be detected. See How to use Tables: Editors and Renderers.
As for the main question, how you can change the image dynamically based on the kind of vehicle change, you can override setValueAt
of the table model. Something like
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();
}
};
Where findImageByColumnCarType
is some method to find the ImageIcon
based on the value
. setValueAt
will be called by the editor, in your case the combobox. So when the value is being set, the value of combo box will be passed to the setValueAt
, and you can use that to call the method findImageByColumnCarType
to get the ImageIcon
. You could have a Map
or something that you use to hold the icons and corresponding values. You can have the method return null
for a car type that has no image
Once you have the ImageIcon
you want, it's just a matter of calling super.setValueAt
to set the new icon for the image column for that same row.
回答2:
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<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); ?
}
}
}
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>(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<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);
}
// ...
}
You can see the results here:
I still need to define a couple of things, but it should be the right way.
来源:https://stackoverflow.com/questions/26142930/complex-use-of-jtable-tablemodel-and-others