AbstractTableModel i edycja tabeli

0

Witam wszystkich ;-)

Piszę aplikację bazodanową, która wyniki zapytań (całą tabelę) wyświetla w tabelce stworzonej za pomocą AbstractTableModel. Od dłuższego czasu borykam się z problemem edycji tej tabelki, próbowałem różnych sposobów, ale nadal nie potrafię sobie z tym poradzić. Dokładnie wygląda to tak, że gdy kliknę dwukrotnie w jedną z komórek mogę ją edytować, ale po kliknięciu w inną komórkę lub inny element okna aplikacji, w edytowanej komórce pojawia się poprzednia wartość :-( . Proszę o pomoc, bo sam naprawdę nie wiem jak to rozwiązać, a tak właśnie wygląda moja klasa tworząca model tabelki:

class MyTableModel extends AbstractTableModel
{
	public MyTableModel(ResultSet rs) throws SQLException
	{
		result = rs;
		try
		{
			rsmd = result.getMetaData();
		}
		
		catch (SQLException e)
		{
			e.printStackTrace();
		}
	}
	
	public int getRowCount()
	{
		try
		{
			result.last();
			return result.getRow();
		}
		
		catch (SQLException e)
	    {
	        e.printStackTrace();
	        return 0;
	    }
	}
	
	public int getColumnCount()
	{
		try
		{
			return rsmd.getColumnCount();
		}
		
		catch (SQLException e)
	    {
	        e.printStackTrace();
	        return 0;
	    }
	}
	
	public Object getValueAt(int r, int c)
	{
		try
		{
			result.absolute(r + 1);
			return result.getObject(c + 1);
		}
		
		catch (SQLException e)
	    {
	        e.printStackTrace();
	        return null;
	    }
	}	
	
	public String getColumnName(int c)
	{
		try{
            return rsmd.getColumnName(c + 1);
		}
		
		catch(SQLException e){
			e.printStackTrace();
            return "";
		}
	}
	
	public boolean isCellEditable(int r, int c)
	{
		return true;
	}
	
	private ResultSet result; 
	private ResultSetMetaData rsmd;
}
0

Zdaje się, że musisz nadpisać metodę setValueAt(...).

0

Próbowałem tak zrobić, ale efekt był taki sam. Całkiem możliwe, że zrobiłem coś nie tak, dlatego prosiłbym o przykładowy fragment kodu?

Chciałem zrobić to w ten sposób:

public void setValueAt(Object value, int r, int c)
	{
		try
		{
			result.absolute(r + 1);
			value = result.getObject(c + 1);
		}
		
		catch (SQLException e)
	    {
	        e.printStackTrace();
	    }
		fireTableDataChanged();
		fireTableCellUpdated(r, c);
	}
0
  1. Dlaczego tak
     fireTableDataChanged();
     fireTableCellUpdated(r, c);

Pierwszy wiersz, to informacja dla tabeli, że gdzieś zmieniły się dane i należy wyświetlić je na nowo. Drugi wiersz to dokładna informacja gdzie nastąpiła zmiana. Wystarczy zatem jeden z tych wiersz.
2. Dane do wyświetlania pobierane są ze zmiennej result typu ResultSet, nie widzę żebyś w metodzie setValueAt(..) zmieniał wartość zmiennej result.

0

No dobrze, w takim razie zadam może banalne pytanie, skoro metoda setValueAt przyjmuje jako parametr value typu Object, który nadpisuje wartość przekazaną przez result.getObject(c + 1) (powinno to wyglądać tak: result.getObject(c + 1) = value), musi pobierać tę wartość. Wiem, że value jest nową wartością, ale skąd się ona bierze? Jaka metoda przekazuje dane metodzie setValueAt?

0

To sie robi "samo", po zakończeniu edycji komórki w JTable, wywoływana jest metoda setValueAt() i przekazywane są do niej: wprowadzona wartość, numer wiersza i numer kolumny edytowanej komórki.

0

W takim razie powinienem nadpisać result, zrobiłem to w taki sposób:

public void setValueAt(Object value, int r, int c)
{
	//result.absolute(r + 1);
	result = (ResultSet)value;

	//fireTableDataChanged();
	fireTableCellUpdated(r, c);
}

Jednak wywala mi błąd java.lang.String cannot be cast to java.sql.ResultSet po zakończeniu edycji i próbie przejścia do następnej komórki.

0

Przeciez result set reprezentuje caly model, a ty edytowales komorke - malenki fragment tego result seta (konkretny rekord, konkretna kolumna) - nie mozesz tak po prostu przypisac do result seta, musisz na result secie wywolac jkas metode ktora zamieni wartosci dla konkretnej komorki w bazie danych.

0

Tak

result = (ResultSet)value;
jest na pewno źle.

  1. Stringa nie możesz rzutować na ResultSet - to ci juz powiedział kompilator.
  2. Ty chcesz jednym Stringiem zamienić cały ResultSet? To powinno chyba wyglądać jakoś tak:
  result.absolute(wiersz+1);
  result.updateString(kolumna+1y,value);

Nigdy dotychczas nie wyświetlałem w JTable ResultSet z możliwością edycji komórek, trochę zatem zgaduję.

0

Tak wiem, że ResultSet reprezentuje cały model, ale wydaje mi się, że jeśli podamy mu odpowiednie wartości takie jak wiersza i kolumny plus wartość powinno to zadziałać podobnie jak to jest z CachedRowSet (właściwie to crs sam pobiera indeksy tabeli). Poprawiłem ten fragment, musiałem dodać tylko rzutowanie i działa:)

public void setValueAt(Object value, int r, int c)
{
	try
	{
		result.absolute(r + 1);
		result.updateString(c+1, value.toString());
	}

	catch (SQLException e)
        {
	       e.printStackTrace();
        }
}

Dzięki wielkie za pomoc.

1 użytkowników online, w tym zalogowanych: 0, gości: 1