Gemeinsame Nutzung eines Models durch eine JTable und eine JComboBox
By MoleHillRocker on Friday, April 9 2010, 22:04 - Code-Schnippsel - Permalink
In den letzten Tagen stand ich vor dem Problem, Daten in einer JTable und einer JComboBox anzeigen zu lassen. Änderungen in der JTable sollten auf die JComboBox übertragen werden und umgekehrt. Da dies jedoch einigen Aufwand in Bezug auf die Synchronisierung der Daten bedeutet, habe ich mich schließlich entschieden ein Model zu entwickeln das von beiden genutzt werden kann.
Das Model
Klasse UserObject
Das Model
public class UserObjectsModel implements TableModel, ComboBoxModel, Constants {
private List<UserObject> data;
private List<EventListener> listenerList = new ArrayList<EventListener>();
private int selectedIndex;
private static UserObjectsModel model;
private UserObjectsModel() {
super();
this.data = new ArrayList<UserObject>();
}
@Override
public int getColumnCount() {
return USER_TABLE_COLUMN_NAMES.length;
}
@Override
public int getRowCount() {
if(data == null)
return 0;
return data.size();
}
@Override
public String getColumnName(int col) {
return USER_TABLE_COLUMN_NAMES[col];
}
@Override
public Object getValueAt(int row, int col) {
UserObject userObject = null;
try {
userObject = data.get(row);
}
catch(NullPointerException npe) {
return null;
}
catch(IndexOutOfBoundsException ioobe) {
return null;
}
switch(col) {
case USER_OBJECT_ID:
return userObject.getUserId();
case USER_OBJECT_FIRST_NAME:
return userObject.getFirstName();
case USER_OBJECT_SECOND_NAME:
return userObject.getSecondName();
case USER_OBJECT_STREET_NAME:
return userObject.getStreetName();
case USER_OBJECT_STREET_NUMBER:
return userObject.getStreetNumber();
case USER_OBJECT_ZIPCODE:
return userObject.getZipcode();
case USER_OBJECT_PLACE:
return userObject.getPlace();
default:
return null;
}
}
@Override
public Class<? extends Object> getColumnClass(int c) {
Object object = getValueAt(0, c);
if(object == null)
return Object.class;
else
return getValueAt(0, c).getClass();
}
@Override
public boolean isCellEditable(int row, int col) {
return false;
}
@Override
public void setValueAt(Object value, int row, int col) {
UserObject userObject = data.get(row);
switch(col) {
case USER_OBJECT_ID:
userObject.setUserId(((Integer) value).intValue());
case USER_OBJECT_FIRST_NAME:
userObject.setFirstName(value.toString());
case USER_OBJECT_SECOND_NAME:
userObject.setSecondName(value.toString());
case USER_OBJECT_STREET_NAME:
userObject.setStreetName(value.toString());
case USER_OBJECT_STREET_NUMBER:
userObject.setStreetNumber(((Short) value).shortValue());
case USER_OBJECT_ZIPCODE:
userObject.setZipcode(value.toString());
case USER_OBJECT_PLACE:
userObject.setPlace(value.toString());
}
fireTableDataChanged();
}
public void addUserObject(UserObject userObject) {
data.add(userObject);
fireTableDataChanged();
}
public void removeUserObject(int row) {
data.remove(row);
fireTableDataChanged();
}
public void removeUserObject(UserObject userObject) {
data.remove(userObject);
fireTableDataChanged();
}
public void clearUsers() {
data.clear();
fireTableDataChanged();
}
public UserObject getUser(int index) {
return data.get(index);
}
public Vector<UserObject> getUsers() {
return new Vector<UserObject>(data);
}
@Override
public void addTableModelListener(TableModelListener listener) {
listenerList.add(listener);
}
@Override
public void removeTableModelListener(TableModelListener listener) {
listenerList.add(listener);
}
@Override
public Object getSelectedItem() {
if(data.size() > 0)
return data.get(selectedIndex);
else
return null;
}
@Override
public void setSelectedItem(Object item) {
for(int i = 0; i < data.size(); i++) {
if(data.get(i).equals(item))
selectedIndex = i;
}
fireContentsChanged();
}
@Override
public void addListDataListener(ListDataListener listener) {
listenerList.add(listener);
}
@Override
public Object getElementAt(int idx) {
if(idx >= 0 && idx < data.size())
return data.get(idx);
else
return null;
}
@Override
public int getSize() {
return data.size();
}
@Override
public void removeListDataListener(ListDataListener listener) {
listenerList.remove(listener);
}
public void fireTableDataChanged() {
fireTableChanged(new TableModelEvent(this));
}
public void fireTableChanged(TableModelEvent event) {
for(EventListener listener : listenerList) {
if(listener instanceof TableModelListener)
((TableModelListener) listener).tableChanged(event);
}
}
public void fireContentsChanged() {
fireContentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED,
selectedIndex, selectedIndex));
}
public void fireContentsChanged(ListDataEvent event) {
for(EventListener listener : listenerList) {
if(listener instanceof ListDataListener)
((ListDataListener) listener).contentsChanged(event);
}
}
public static UserObjectsModel getInstance() {
if(model == null)
model = new UserObjectsModel();
return model;
}
}Klasse UserObject
public class UserObject {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int userId;
@Basic
private String firstName;
@Basic
private String secondName;
@Basic
private String streetName;
@Basic
private short streetNumber;
@Basic
private String zipcode;
@Basic
private String place;
public UserObject() {
super();
}
public UserObject(String firstName, String secondName, String streetName,
short streetNumber, String zipcode, String place) {
super();
this.firstName = firstName;
this.secondName = secondName;
this.streetName = streetName;
this.streetNumber = streetNumber;
this.zipcode = zipcode;
this.place = place;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getSecondName() {
return secondName;
}
public void setSecondName(String secondName) {
this.secondName = secondName;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public short getStreetNumber() {
return streetNumber;
}
public void setStreetNumber(short streetNumber) {
this.streetNumber = streetNumber;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public String getPlace() {
return place;
}
public void setPlace(String place) {
this.place = place;
}
public String toString() {
return "UserObject [ " + userId + " " + firstName + " " + secondName + " ]";
}
}
Interface Constantspublic interface Constants {
public static final String[] USER_TABLE_COLUMN_NAMES = { "User-ID", "First name",
"Last name", "Street name", "Street number", "Zip code", "Place" };
public static final int USER_OBJECT_ID = 0;
public static final int USER_OBJECT_FIRST_NAME = 1;
public static final int USER_OBJECT_SECOND_NAME = 2;
public static final int USER_OBJECT_STREET_NAME = 3;
public static final int USER_OBJECT_STREET_NUMBER = 4;
public static final int USER_OBJECT_ZIPCODE = 5;
public static final int USER_OBJECT_PLACE = 6;
}
Das Model kann nun durch Aufruf der Methode #setModel(UserObjectsModel.getInstance())an die JTable/JComboBox gebunden werden.
Comments
Hi MoleHillRocker,
danke für deinen Post, die Idee hat mir schon sehr geholfen, eigene Objekte im TableModel zu verwalten.
Nun habe ich allerdings noch das Problem, dass ich die selektierten Daten aus der Tabelle im Modell wiederfinden muss, z.B. um eine selektierte Zeile zu löschen.
Da die Tabelle nach Spalten sortiert werden kann, liefert die Zeilennummer der Selektion keinen Bezug zum Index des Eintrags in der Objekt-Liste im Modell.
Vermutlich hast du ein ähnliches Problem gelöst. Für einen Tipp wäre ich dankbar.
Danke und Gruß,
Michael
Hallo Michael,
schau dir hierzu mal die Methode
convertRowIndexToModel()an. Dieser übergibst du die aktuell selektierte Zeile und erhältst einen absoluten Index der immer auf das gleiche Element im Model verweist, d.h. trotz unterschiedlicher Sortierung gibtconvertRowIndexToModel()immer den Index zurück, den die Zeile vor der ersten Sortierung hatte.Grüße,
Lars