Swing jcombobox als jtable-editor: neues Item auswählen

markusk21

Mitglied
Hallo zusammen, ich hab mal wieder ein Problem.
Ich habe eine JComboBox als Celleditor eingerichtet - funktioniert gut soweit.

Aber wie krieg ich es hin, über diesen Celleditor ein neues Element anzulegen?
Konkret:
Das ist der Editor:
Java:
    @SuppressWarnings("unchecked")
    private javax.swing.JComboBox getWgEditor() {
	java.util.List<data.Wg> tmpListe = (java.util.List<data.Wg>) session.createQuery("from data.Wg").list();
	javax.swing.JComboBox comboBox = new javax.swing.JComboBox(tmpListe.toArray());

	comboBox.setEditable(true);
	comboBox.addActionListener(new java.awt.event.ActionListener() {

	    /**
	     * Bei "Not in List" wird eine neue WG angelegt.
	     */
	    public void actionPerformed(ActionEvent ae) {
		if ((((javax.swing.JComboBox)ae.getSource()).getSelectedIndex() == -1) &&
			(!((javax.swing.JComboBox)ae.getSource()).getSelectedItem().toString().isEmpty()))
		    saveNewWg(((javax.swing.JComboBox)ae.getSource()).getSelectedItem().toString());
	    }
	});
	return comboBox;
    }

Hier wird die wg gespeichert:
Java:
    /**
     * speichert eine Neue WG in die Datenbank
     * @param wgName
     */
    private void saveNewWg(String wgName){
	if (!this.wg.getWgName().matches(wgName)){
	    logger.debug("wgs: this.wg: " + this.wg.getWgName()+ "newString: " + wgName);
	    wg = new data.Wg();
	    wg.setWgName(wgName);
	    int selectedRow = this.getSelectedRow();
	    org.hibernate.Transaction tx = session.beginTransaction();
	    session.saveOrUpdate(wg);

	    tx.commit();
	    getColumnModel().getColumn(1).setCellEditor(new javax.swing.DefaultCellEditor(this.getWgEditor()));
	    logger.debug("Neue Wgid?: " + wg.getId());
	    logger.debug("Selected Row: " + selectedRow);
	    model.setValueAt(wg, selectedRow, 1);
	    logger.debug("Selected Uni: " + getModel().getValueAt(selectedRow, 1));
	}
    }
Funktioniert auch gut soweit - die wg erhält aus der saveOrUpdate-Methode sogar die Id des neuen Datensatzes zurück. Wg ist danach also ein vollwertiges, persistentes Objekt.

Aber model.setValueAt funktioniert nicht! Scheinbar wird beim edieren einer Zelle nicht die Zeile selektiert (die logger-zeile):
Code:
Selected Uni: null

Ich hab schon nach einem "Edit-Listener" oder so gesucht, aber der TableModelListener hat ja nur das tableChanged-Event, das wird nicht ausgelöst (bisher).

Also, am liebsten würde ich der Combobox sagen, sie soll das neue Element aus der Edit-Prozedur zurückgeben.
Die weniger "schöne" Lösung wär wohl, aus der Zeile das geänderte objekt in der Datenbank zu speichern und die Tabelle schlicht neu einzulesen.
Komm aber bei beiden Ideen nicht weiter 🙁
 
Zuletzt bearbeitet:
Hmm, ok... Die ganze Tabellenklasse:
Java:
package gui.tables;

import java.awt.event.ActionEvent;
import javax.swing.event.TableModelEvent;
import meinekomponenten.AutofitTableColumns;
import org.apache.log4j.Logger;
import org.apache.log4j.Level;
import java.awt.Component;
import java.awt.Dimension;
import java.io.Serializable;
import java.util.Hashtable;
import javax.swing.table.*;
import org.hibernate.Session;

/**
 *
 * @author markus
 */
public class HochschulenTabelle extends javax.swing.JTable implements Serializable{
    Logger logger = Logger.getLogger("gui.tables.HochschulenTabelle");
    org.hibernate.Session session = persistence.HibernateUtil.getSessionFactory().openSession();
    gui.tables.HochschuleList2TableModel model;
    data.Wg wg = new data.Wg();	// Für neue WG!
    String hql;

    /**
     * Default Konstructor to be set up with hql-code, NOT sql!
     * @param hql   hql- code for hibernate
     */
    public HochschulenTabelle(String hql){
	super();
	logger.setLevel(Level.DEBUG);
	this.hql = hql;
	
	model = new gui.tables.HochschuleList2TableModel(session, session.createQuery(hql));
	setModel(model);

	javax.swing.table.TableCellEditor tCellEditor = new javax.swing.DefaultCellEditor(this.getWgEditor());

	getColumnModel().getColumn(1).setCellEditor(tCellEditor);
	getColumnModel().getColumn(0).setCellEditor(new javax.swing.DefaultCellEditor(new javax.swing.JTextField()));

	logger.debug("model: " + model.getColumnName(0) + " "+ model.getColumnName(1));

	AutofitTableColumns.autoResizeTable(this, true);

	model.addTableModelListener(new javax.swing.event.TableModelListener() {

	    public void tableChanged(TableModelEvent tme) {
		tableModelEvent(tme);
	    }
	});
	setAutoCreateRowSorter(true);
	setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
	setFont(new java.awt.Font("SansSerif", java.awt.Font.PLAIN, 12));
    }

    /**
     * Creates a standard HochschulenTabelle with folowing hql-code:
     * from data.Hochschule h order by h.wg, h.hochschule
     */
    public HochschulenTabelle(){
	this("from data.Hochschule h order by h.wg, h.hochschule");
    }

    /**
     * Liefert eine JCombobox die die WGs enthält
     * @return
     */
    @SuppressWarnings("unchecked")
    private javax.swing.JComboBox getWgEditor() {
	java.util.List<data.Wg> tmpListe = (java.util.List<data.Wg>) session.createQuery("from data.Wg").list();
	javax.swing.JComboBox comboBox = new javax.swing.JComboBox(tmpListe.toArray());

	comboBox.setEditable(true);
	comboBox.addActionListener(new java.awt.event.ActionListener() {

	    /**
	     * Bei "Not in List" wird eine neue WG angelegt.
	     */
	    public void actionPerformed(ActionEvent ae) {
		if ((((javax.swing.JComboBox)ae.getSource()).getSelectedIndex() == -1) &&
			(!((javax.swing.JComboBox)ae.getSource()).getSelectedItem().toString().isEmpty()))
		    saveNewWg(((javax.swing.JComboBox)ae.getSource()).getSelectedItem().toString());
	    }
	});
	return comboBox;
    }

    private void tableModelEvent(TableModelEvent tme){
	logger.debug("Model-Event! Zeile: " + tme.getFirstRow());
	String type ="";
	switch (tme.getType()){
	    case TableModelEvent.UPDATE: type = "Update";
	    break;
	    case TableModelEvent.DELETE: type = "Delete";
	    break;
	    case TableModelEvent.INSERT: type = "INSERT";
	    break;
	}
	logger.debug("Model-Event! Type: " + tme.getType() + " " + type);
	logger.debug("Model-Event! Spalte: " + tme.getColumn());
    }
    /**
     * speichert eine Neue WG in die Datenbank
     * @param wgName
     */
    private void saveNewWg(String wgName){
	if (!this.wg.getWgName().matches(wgName)){
	    logger.debug("wgs: this.wg: " + this.wg.getWgName()+ "newString: " + wgName);
	    wg = new data.Wg();
	    wg.setWgName(wgName);
	    int selectedRow = this.getSelectedRow();
	    org.hibernate.Transaction tx = session.beginTransaction();
	    session.saveOrUpdate(wg);

	    tx.commit();
	    getColumnModel().getColumn(1).setCellEditor(new javax.swing.DefaultCellEditor(this.getWgEditor()));
	    logger.debug("Neue Wgid?: " + wg.getId());
	    logger.debug("Selected Row: " + selectedRow);
	    model.setValueAt(wg, selectedRow, 1);
	    logger.debug("Selected Uni: " + getModel().getValueAt(selectedRow, 1));
	}
    }

    /**
     * Liest die Datenbank neu ein - bei Änderungen von außerhalb in der Datenbank
     */
    public void requery(){
	getColumnModel().getColumn(1).setCellEditor(new javax.swing.DefaultCellEditor(this.getWgEditor()));
	this.model.requery();
    }

    public void removeRow(int row){
	int selected = this.getRowSorter().convertRowIndexToModel(this.getSelectedRow());
	model.removeRow(selected);
    }

    /**
     * neue Abfrage
     * @param hql
     */
    public void query(String hql){
	this.hql = hql;
	model.setQuery(session.createQuery(hql));
    }

    public String getHql() {
	return hql;
    }

    public void setHql(String hql) {
	this.hql = hql;
    }

    public HochschuleList2TableModel getHochschuleModel() {
	return model;
    }


    public Session getSession() {
	return session;
    }

    public void setSession(Session session) {
	this.session = session;
    }

    public TableModel getDataModel() {
	return dataModel;
    }

    public void setDataModel(TableModel dataModel) {
	this.dataModel = dataModel;
    }

    public Hashtable getDefaultEditorsByColumnClass() {
	return defaultEditorsByColumnClass;
    }

    public void setDefaultEditorsByColumnClass(Hashtable defaultEditorsByColumnClass) {
	this.defaultEditorsByColumnClass = defaultEditorsByColumnClass;
    }

    public Hashtable getDefaultRenderersByColumnClass() {
	return defaultRenderersByColumnClass;
    }

    public void setDefaultRenderersByColumnClass(Hashtable defaultRenderersByColumnClass) {
	this.defaultRenderersByColumnClass = defaultRenderersByColumnClass;
    }

    public Component getEditorComp() {
	return editorComp;
    }

    public void setEditorComp(Component editorComp) {
	this.editorComp = editorComp;
    }

    public Dimension getPreferredViewportSize() {
	return preferredViewportSize;
    }

    public void setPreferredViewportSize(Dimension preferredViewportSize) {
	this.preferredViewportSize = preferredViewportSize;
    }

    public static void main(String args[]) {
	javax.swing.JFrame frame = new javax.swing.JFrame("HochschulenTabelle Test...");
	javax.swing.JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
	jScrollPane1.setViewportView(new HochschulenTabelle());
	frame.setLayout(new java.awt.GridLayout(1, 1));
	frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
	frame.add(jScrollPane1);
	frame.pack();
	frame.setVisible(true);
    }
}

Dann ist hier noch die Modell-Klasse:
Java:
package gui.tables;

import java.util.List;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;
import java.io.Serializable;

/**
 *
 * @author markus
 */
public class HochschuleList2TableModel 
	extends gui.tables.AbstractList2TableModel
	implements Serializable{

    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("gui/resources/Person_Hochschule_WG");
    java.util.List<data.Hochschule> content;
    Logger logger = Logger.getLogger("gui.tables.HochschuleList2TableModel");

    public HochschuleList2TableModel(org.hibernate.Session session, org.hibernate.Query query){
	super(session, query);
	logger.setLevel(Level.DEBUG);
    }

    public void removeRow(int row){
	if (javax.swing.JOptionPane.showConfirmDialog(null, "Wollen Sie " + this.content.get(row).getHochschule()
		 + " wirklich löschen? Alle erfassten Daten gehen dabei endgültig verloren!", "Hochschule löschen?", javax.swing.JOptionPane.YES_NO_OPTION)
		== javax.swing.JOptionPane.YES_OPTION) {
	    org.hibernate.Transaction tx = this.session.beginTransaction();
	    this.session.delete(this.content.get(row));
	    tx.commit();
	}
	this.requery();
    }

    @SuppressWarnings("unchecked")
    @Override
    public void setupModelContent(){
	this.content = (java.util.List<data.Hochschule>)this.query.list();
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
	return true;
    }

    public Object getValueAt(int rowIndex, int columnIndex){
	Object value = null;
	switch (columnIndex){
	    case 0:
		value = content.get(rowIndex);
		break;
	    case 1:
		value = content.get(rowIndex).getWg();
		break;

	}
	return value;
    }

    public List<data.Hochschule> getContent() {
	return content;
    }

    /**
     * Liefert die Person der betreffenden Zeile
     * @param rowIndex
     * @return data.Person
     */
    public data.Hochschule getHochschuleAt(int rowIndex){
	return (data.Hochschule)getObjectAt(rowIndex);
    }

    @Override
    public String getColumnName(int columnIndex){

	switch (columnIndex){
	    case 1: return bundle.getString("Wg.text");
	    case 0: return bundle.getString("Hochschule.text");
	    default: return "";
	}
    }
    
    @Override
    public Class getColumnClass(int columnIndex){
	switch (columnIndex){
	    case 0: return data.Hochschule.class;
	    case 1: return data.Wg.class;
	    default: return String.class;
	}
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex){
	logger.debug("Zelle geändert: (" + rowIndex + "," + columnIndex + "): " + aValue);
	org.hibernate.Transaction tx = session.beginTransaction();
	data.Hochschule hochschule = content.get(rowIndex);
	
	if (columnIndex ==0)
	    hochschule.setHochschule((String)aValue);
	
	session.update(hochschule);
	tx.commit();
    }

    public int getColumnCount(){
	return 2;
    }
}

Die abstrakte Klasse macht nicht viel 🙂

Und wie gesagt, mit setValueAt hab ich es versucht, weiß aber nicht, wie ich die Zeile rauskriegen soll...
 
Jup, danke Ebenius!
Hab den ganzen Kram aus der Tabellenklasse rausgeschmissen und im Model die setValueAt folgendermaßen angepasst:

Java:
    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex){
	
	logger.debug("Zelle geändert: (" + rowIndex + "," + columnIndex + "): " + aValue);
	data.Hochschule hochschule = content.get(rowIndex);

	if (columnIndex == 0)
	    hochschule.setHochschule((String)aValue);

	if (columnIndex == 1)
	{
	    if (aValue instanceof String) {
		hochschule.setWg(saveNewWg((String)aValue));
		
	    }else if (aValue instanceof data.Wg){
		hochschule.setWg((data.Wg)aValue);
	    }
	}
	
	org.hibernate.Transaction tx = session.beginTransaction();
	session.update(hochschule);
	tx.commit();
    }

So läuft es (natürlich) 😳
 

Zurück
Oben