Werte in JTable editieren und weiter geben

Myar

Mitglied
Hallöchen!

Ich steh vor nem riesen Problem und bekomm schon graue Haare deswegen...

Ich habe eine JTable gebastelt mit nem TableModel welche wunderbar die Werte aus vier verschiedenen ArrayLists einliest und in vier Spalten Reihe für Reihe jeden Wert in seiner Spalte, wiedergibt.
Soweit so gut. War heilfroh das geschafft zu haben.

Nun, jetzt stehe ich vor dem Problem, dass ich den Inhalt der Zellen editieren will, diesen neuen Wert dann auch an eine andere Methode übergeben.
Durch Doppelklick kann ich editieren, also die Zellen sind editierbar, die Methode, welche mir die ArrayList mit neuen Werten überschreibt steht auch (in einer anderen Klasse).

Nur wenn ich in eine zelle dann was eintippe und Enter sage, bekomme ich zig Exceptions ausgegeben...

Ich habe mich nun durch zig INetseiten, nen Buch und die API gewühlt, aber ich verstehe das einfach nicht.

Naja, Code ist wohl irrelevant, da das bisherige funktioniert...

Also nochmal kurz:
Die Table holt sich Strings, die sie wunderschön in Reihen und spalten darstellt.
Nun will ich doppelklicken, einen Wert verändern und dann, nachdem der Inhalt der Zelle geandert wurde, den Zelleninhalt in eine neue Methode (in einer anderen Klasse) übergeben.

Das ist das Stück das ich einfach nicht hinbekomme :(

ich hoffe mir kann jemand helfen...

Gruß
Myar
 
Hallo ...
das is eigentlich recht einfach ... du hast in deinem Table Model 2 wichtige funktion
die setValueAt und die getValueAt.
Mit der getValueAt setzt du die werte aus deiner internen Datestruktur in die Tabelle und mit der SetValueAt setzt kannst du werte in deine Interne Datestruktur setzen ... methoden zum speichern usw musst du dann selber schreiben ... ;) aber das bekommst du hin ....
Denk dran, dass wenn der Anwender Zellen editieren kann dass du bei jedem verlassen der Tabelle prüfst, ob der CellRenderer dicht ist, weil sonst die Zelle in der er noch offen ist ein möglicherweise geänderter wert nicht gespeichert ist.

Gruß

Gora

P.S.: wenn du brauchst suchich dir dafür auch noch code raus .. habe hier nur gerade keinen Parat ... müsstest du dich bis morgen gedulden! :)
Viel Erfolg
 
Hallöchen!

Danke für die Antwort!

Nun also die getValueAt Methode is ja bereits drin:

Code:
public Object getValueAt(int row, int column) {
		if (column == 0)
			return Array1.get(row); // Bestimmte Parameter
		if (column == 1)
			return Array2.get(row); // Bestimmte Werte
		if (column == 2)
			return Array3.get(row); // Vergleichsparameter
		if (column == 3)
			return Array4.get(row); // Vergleichswerte
		else
			return Array5.get(row); // dieses Array setzt  nur Fehlermeldungen
	}

Soweit hab ichs verstanden ;)
Wenn die Tabelle dann also offen ist, kann man mit einem Blick schauen, ob Parameter und Werte in einer bestimmten Datei mit der aus einer Vorlage übereinstimmen (die Methode die den Vergleich anstellt steht).
Tun sie das nicht, werden durch eine if-Abfrage in die fünfte ArrayList Fehlermeldungen gesetzt und die Tabelle holt sich diese dann.

Wenn das der Fall ist, soll man nun den falschen wert berichtigen können. Das ist der Zweck der Sache (nochmal ums etwas anschaulicher zu machen... hoffe ich *g*).

Die Methode, die dann den neuen Wert in eine seperate ArrayList packt um dann die Datei neu zu schreiben, schaut so aus:

Code:
System.out.println("Bitte den zu ändernen Wert angeben (Zeile):");
		w = eingabe.nextInt();

		System.out.println("Wert an Stelle " + w + ": " + werte.get(w));

		System.out.print("Wert ändern in: ");
		wertneu = eingabe.next();

		ArrayList<String> werte3 = new ArrayList<String>();
		datei2 = new FileReader(dataName); // Datei einlesen
		leser2 = new BufferedReader(datei2); // Datei zwischenspeichern
		String zeile2 = leser2.readLine();
			
		for (int j = 0; j < werte.size(); j++) {
				
		// Die zeilen aulassen, die mit '#'als Kommentar
		//gekennzeichnet sind
		if (!zeile2.matches("\\s*#.*")) {
			// hier schaut er, ob man grad an Stelle w ist
                                               if (j == w) {
			werte3.add(wertneu +
		"  ## " + formatter.format(currentTime));
		// vor dem "=" ist der Parameter, in der Liste will ich aber nur den Wert			}
		wert2 = (zeile2.substring(zeile2.indexOf("=") + 1, zeile2
								.length())).trim();

		werte3.add(wert2);
	}else{
	j--;
	}
	zeile2 = leser2.readLine();
	}
			
	for (int i = 0; i < para.size(); i++) {
	writer.write(para.get(i) + " = " + werte3.get(i) + "\r\n");
			}
			
	datei2.close();
	writer.flush();
	writer.close();

So, im Moment gibt man noch alles in der Konsole ein.
w steht dabei für die Stelle in der Array List und neuerwert ist halt das, was neu reingepackt ird.

Also die eigentlichen Listen werden vorher einfach eingelesen (hab ich hier mal weggelassen). Dann sieht man ja in der Tabelle was nicht stimmt.
Jetzt sagt der einem in der Konsole, dass man die Stelle (also w) angeben soll, zeigt einem den ist Wert an und fragt nach dem neuen wert.
Den gibt man ein und die ArrayList3 wird mit den selben Daten befüllt wie vorher die Liste, nur an der Stelle w kommt halt der neue Wert.
Nun soll sich die Methode also anstatt über die Konsole von der Tabelle das w und den neuen wert holen (dabei soll die Methode auch erst gestartet werden, wenn man die Zelle fertig editiert hat).

Hm, nach weiterem Googeln hab ich aber net wirklich herausgefunden, wie ich die setValueAt Methode einsetze :(

So sieht das TableModel aus:

Code:
package Programmieraufgabe;

import java.util.ArrayList;
import javax.swing.table.DefaultTableModel;

public class CustomTableModel extends DefaultTableModel{
	private ArrayList<String> one, one2, two, two2, three = null;

	/** Creates a new instance of CustomTableModel */
	public CustomTableModel(ArrayList<String> one, ArrayList<String> one2, ArrayList<String> two,
			ArrayList<String> two2, ArrayList<String> three) {
		this.one = one;
		this.one2 = one2;
		this.two = two;
		this.two2 = two2;
		this.three = three;

	}
	
	public Object getValueAt(int row, int column) {
		if (column == 0)
			return one.get(row);
		if (column == 1)
			return one2.get(row);
		if (column == 2)
			return two.get(row);
		if (column == 3)
			return two2.get(row);
		else
			return three.get(row);
	}

	public int getRowCount() {
		if (one == null)
			return 0;
		return one.size();
	}

	public int getColumnCount() {
		return 5;
	}
	
	public String getColumnName(int index){
		if(index == 0)
		return "Parameter";
		if(index == 1)
		return "Wert";
		if(index == 2)
		return "Parameter";
		if(index == 3)
		return "Wert";
		else
		return "Meldung";
	}
	
	public boolean isCellEditable()
	{
	    return true;
	}
}

Nunja, mit ein wenig Code und dem richtigen Denkansatz bekomm ich das bestimmt hin :)
Was ich brauch ist immer der richtige Anstoß *hehe*
Wäre sehr nett, wenn du mir da nochmal helfen könntest!
 
hm okay
Soweit so guut.
Du musst in deinem TabelModel die Funktion setValueAt() einfügen. Diese Funktion behandelt wie mit Eingaben in die tabelle verfahren wird.

Du leitest dein TabelModel vom DefaultTableModel ab ... is zu lässig nicht weiter ein Problem.
Im DefaultTableModel is die methode setValueAt(int row, int column) schon drin also muss sie überschrieben werden...

Du sagtest du hast 4 ArrayListen, aus denen du jeweils eine Spalte der Tabelle erstellst.

Code:
public class MyTableModel extends AbstractTableModel {

     //Hier felder für die Daten initialisieren ..
     ArrayList eins = new ArrayList();
     // usw.....

    /**
     * Default Konstruktor 
     */
    public MyTableModel() {
    }

    /** 
     * Hier die Daten an die instanz des tabelmodels übergeben
     */
    public MyTableModel(ArrayList eins,.... ) throws NullPointerException {

        if (eins != null) {
            this.eins = eins;
        } else {
            throw new NullPointerException(
                "Fehler im Konstruktor!");
        }
        this.fireTableDataChanged();
    }

    /**     
     * Methode getRowCount 
     * @return int Anzahl der Zeilen der Tabell
     *         Also das Maximum deiner längsten Liste
     */
    public int getRowCount() {
        return eins.size();

    }

    /** 
     * Methode getColumnCount
     * @return Konstante 4 
     *      
     */
    public int getColumnCount() {
        return 4;
    }

    /** 
     * Die Funktion getValueAt liest an der übergebenen Position zeile,spalte 
     * den Wert aus und gibt ihn als entsprechendes Objekt zurück.
     *
     * @param      zeile    Position in der Tabelle y
     * @param      spalte   Position in der Tabelle x
     * @return     Object 
     *
     */
    public Object getValueAt(int zeile, int spalte) {
        if (column == 0)
			return eins.get(row);
		if (column == 1)
			return zwei.get(row);
		....
    }

    /**    
     * Methode getColumnName
     * 
     * @param spalte  
     * @return String mit dem Spaltennamen
     */
    @Override
    public String getColumnName(int spalte) {
        if (spalte == 0)
            return "Spalte1";

        else
            return "Spalte2";


    }


    // Methode isCellEditable returns true

    /**     
     * Methode isCellEditable 
     * @param zeile
     * @param spalte
     * @return  true Die komplette Tabelle soll editierbar sein 
     */
    @Override
    public boolean isCellEditable(int zeile, int spalte) {
        return true;
    }
    
    /**
    *
     *  @param  eintrag  Der Inhalt der Zelle  
     *  @param  zeile
     *  @param  spalte
     */
    public void setValueAt(Object eintrag, int zeile, int spalte) {

      switch(spalte){

        case 1 : eins.get(zeile) = eintrag;

        case 2 : zwei.get(zeile) = eintrag; 
        // usw ...

        }
        this.fireTableDataChanged();

    }

}


So ... puh lange nicht mehr sowas gemacht ... arbeite eigentlich im mom nur mit Comboboxen in Tabellen ... naja sollte aber Klappen ...
Ich hoffe das hilft dir weiter !

Gruß Gora
 
Huhu!

okay, ich bekomme keine Exceptions mehr, wenn ich was in die Zelle schreibe, aber der neue Wert bleibt nicht bestehen *seufz*
Ich muss halt dazu sagen, dass GUI und SWING nun seit ein paar Tagen Neuland sind für mich, von daher diese Fragerei.

Also ich doppelklicke nun in die Zelle, ändere den wert und drück Enter.
Er verlässt die Zelle ohne Anstallten, aber setzt den alten Wert wieder rein...

Ich schätze mal, dass ich im Case Block nun dem Objekt eintrag einen String zuweisen muss, der sich den neuen Wort holt, gell?

Also die beiden Methoden schauen nun so aus:

Code:
public Object getValueAt(int row, int column) {
		if (column == 0)
			return one.get(row);
		if (column == 1)
			return one2.get(row);
		if (column == 2)
			return two.get(row);
		if (column == 3)
			return two2.get(row);
		else
			return three.get(row);
	}
	
public void setValueAt(Object eintrag, int row, int column) {
			
	switch(column){
	      	
	        case 0 : eintrag = one.get(row);
	      			break;

	        case 1 : eintrag = one2.get(row);
	        		break;
	        
	        case 2 : eintrag = two.get(row);
	        		break;
	        
	        case 3 : eintrag = two2.get(row); 
	        		break;

	        }
	        this.fireTableDataChanged();

	    }

ich schätze mal, es liegt daran, dass eintrag nun wieder gleich dem Inhalt der ArrayList gesetzt wird.
Anders herum geht aber nicht, da Eclipse sonst meckert, dass links vom "=" eine Variable stehen muss.
 
ich schätze mal, es liegt daran, dass eintrag nun wieder gleich dem Inhalt der ArrayList gesetzt wird.
Richtig!
Ein Blick in die API Dokumentation hätte aber schnell eine Methode gezeigt, die genau das macht, was du brauchst...
Code:
public void setValueAt(Object eintrag, int row, int column) {
            
    switch(column){
              
            case 0 : if(row >= one.size())
                               one.add(eintrag);  // neuer Eintrag, wird am Ende der ArrayList eingefuegt
                         else
                                 one.set(eintrag,row); //   Ersetz den Eintrag an der Stelle "row"
                      break;
...
            this.fireTableDataChanged();

        }

*grüssle*
MeinerEiner
 
Ja, mit der API muss ich mich noch anfreunden.
Für mich ist das stets chinesisch bzw. habe ich es noch nicht wirklich drauf, die Infos so rauszufiltern, dass sie für mein problem passen *seufz*

Aber vielen Dank für deine Mühe mir den Code zu präsentieren.
Klappt wunderbar!

Nun ist das Programm fast fertig, eigentlich wohl nen Ding von ein paar Stunden, da ich mir Java noch aneigne nun etwas von Wochen *g*
Nun, ich habe mir nun gedacht, dass wenn ich einen wert ändere, ich dann auch die Methode schreiben aufrufe:

Code:
public void setValueAt(Object eintrag, int row, int column) {
        
	    switch(column){
	              
	    case 0 : one.set(row, eintrag); // Ersetz den Eintrag an der Stelle "row"
	    		 Schreiben s = new Schreiben();
s.schreibe();

// usw.

Ob das wohl klappt?
Dann wolle ich in der Schreiben Klasse den neuen Wert der Variablen "neuerwert" (siehe Code weiter oben) übergeben, ungefähr so:

Code:
wertneu = (String)MyTableModel.one.get(w);

Tjoah, wie übergebe ich nun noch der Variablen "w" aus der Klasse Schreiben, die Stelle in der ArrayList, die dort in der Tabelle ausgegeben wird?

Da dieses table Model noch etwas kompliziert für mich ist, wüsste ich nun nicht, wie ich das da raus hole...

Nunja, falls ich nun zuviel verlange versteh ich das, ansonsten freue ich mich nochmals sehr über Hilfe :)

Gruß
Myar
 
So richtig verstanden hab ich dich nicht... Aber vielleicht ist es ja damit getan, wenn du einfach alle Werte, die du benötigst, deiner schreibe Methode mitübergibst..
zum Beispiel:
Code:
public void setValueAt(Object eintrag, int row, int column){
         ...
         s.schreibe(eintrag,row,column);
}


*grüssle*
MeinerEiner
 
Hm, hm...
Ich versuch nochmal es zu erkären...

Also das "w" ist die Stelle im Array die durch die Zelle in der JTable dargestellt wird.

Das heißt, wenn ich einen Wert in der Tabelle editiere, springt er in die Methode "schreibe", dort schnappt er sich über "w" die Stelle im Array deren Wert da gerade in der Tabelle geändert wurde, durchläuft eine Schleife, in der er die neue ArrayList werte3 (porbename) mit den Werten befüllt, aber am Index "w" packt er den Wert hinein, der neu eingeben wurde. Dann schreibt er die Datei komplett neu mit den Werten der ArrayList und der Fehler wurde korrigiert. :)
Das ist das, was ich an "neuertwert" übergeben habe.
Habe das gerade mal durchgetestet, das "w" muss ich noch über die Konsole eingeben, also gucken, welche Zeile ich da eigentlich editiere, aber er hat wunderschön den Wert, den ich in die Tabelle geschrieben habe auch in die Datei geschrieben.
Nun fehlt halt noch, dass ich den Array Index "w" nicht über die Konsole eingeben muss, sondern er sich "w" darüber holt, wo ich die Tabelle editiert habe und somit weiß, welcher Index der ArrayList das war ;)

*schluck* verständlicher?
Ich schätze mal, das mit deiner Lösung grad zu machen, würde heißen die ganze Methode neu schreiben zu müssen(?)

Ich weiß, wahrscheinlich habe ich das viel zu kompliziert gelöst, aber außer ArrayLists kenne ich noch keine dynamischen "Behälter/Listen" mit denen ich das machen könnte.
 
Moin!

So, war gar net so schlecht, dass keien Antwort mehr kam.
man muss nur mal ne Nacht drüber grübeln und schon hat ich ne Lösung.
Hab das ganze mit zwei Variablen gelöst, die in der Methode setValueAT sich die Zeile und die Spalte schnappen und die dann in Schreiben übergeben.
So funktioniert das wunderbar dynamisch und er weiß, in welcher SPalte und in welcher Zeile die änderung vorkam!

Vielen Dank euch beiden!

Guß
Myar
 
Zurück