Trzy pytania w temacie JTable

0

Hej,

Pyt 1.
Czy można zmieniać BackgroundColor każdej komórki z osobna (w zależności od fluktuacji jakiejś zmiennej zmienia się również kolor tła danej komórki w JTable)?

Pyt 2.
Czy można zaznaczać wiele pojedynczych komórek na raz tradycyjnie z wciśniętym CTRL'em (tzn. sprawić by JTable pamiętało o wcześniej zaznaczonych pojedynczych komórkach - MULTIPLE selection model niestety się nie sprawdza, gdyż zaznacza interwałowo komórki, a nie pojedynczo, te które wybrałem wcześniej)?

Pyt 3.
Czy można zmienić styl zaznaczania tak, by podczas zaznaczenia komórek zmieniało się ich obramowanie, a nie tło (czyli tło pozostaje cały czas np. białe, a obramowanie zmienia kolor na np. niebieski)?

Będę niezmiernie wdzięczny za odpowiedzi i porady.

Pozdrawiam ciepło!

0

1, 2 i 3. Tak (MULTIPLE się sprawdza).

0

To wspaniale! :) A czy mogę jeszcze prosić o delikatne rozwinięcie odpowiedzi w kierunku ich praktycznej implementacji? :)

1

Możesz.

JTable table = new JTable(...);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
//pętla po kolumnach, dla każdej kolumny kol, którą chcesz nietypowo rysować
  kol.setCellRenderer(new MyRendererThisColumn());

Przykładowy kod własnego renderera dla kolumny, w której są liczby całkowite:

class MyRendererThisColumn implements TableCellRenderer
{
    //------------------------
    public Component getTableCellRendererComponent(JTable t,Object value,boolean selected,boolean hasFocus,int row,int col)
    {
        Integer i = (Integer)value;
        JLabel cell=new JLabel(""+i);
        if(i<0)
        {
            cell.setBackground(Color.RED);
        }
        return cell;
    }
}

Kod nie testowany.

0

A właśnie, widzisz! Zapomniałem napomknąć, że zależy mi na wprowadzaniu zmian w pustej komórce. Właśnie ze względu na chęć uniknięcia korzystania z JLabeli :/ Mam macierze nawet po 4000 elementów więc stąd też moje zawzięte poszukiwania sposobu na zmianę BG pustej komórki :/

0

A dlaczego nie JLabel? Jest za wolny?

0

Wiesz, chciałbym by komórka reagowała tylko na 3 stany - 1 stan, to informacja o zaznaczeniu jakiegoś innego elementu w innej klasie i na tej podstawie pojawia się owo np. niebieskie obramowanie komórki JTable (ale bez ingerencji w tło); 2 stan, to zmieniająca się dynamicznie wartość jakiegoś wektora, która odzwierciedla się zmianą tła komórki w JTable; 3 stan, to też wartość jakiegoś wektora i skutkuje pisaniem jakiegoś tekstu w komórce w zależności od zmian wartości zmiennej (np. wyświetla 1, 2, 3 itd.). Wszystko to fajnie można osiągnąć z JLabelami i super można też załatwić kwestię obramowania reagującego na zaznaczanie czegoś innego w innej klasie, ale kłopotem jest implementacja tylu JLabeli no i fakt, że fakt faktem są wolne troszkę :/ Dlatego tak zawzięcie szukam możliwości działania na pustych komórkach. Gdyby można było zmieniać tło dla pojedynczej pustej komórki to byłoby wspaniale.

0
  1. Do wyświetlenia dowolnej komórki w tabeli służy jakiś komponent, JLabel jest z nich wszystkich najwolniejszy?
  2. Nie ma implementacji wielu komórek, jest jedna metoda getTableCellRendererComponent wyświetlająca wszystkie komórki w kolumnie, a można tak podpiąć własnego renderera, że jedna metoda wyświetla wszystkie komórki tabeli.
  3. Po zmianach w modelu (zmianach zawartości komórek) trzeba wywołać metodę fireTableDataChanged lub jakąś pokrewną, dokładniej informującą co się zmieniło (komórka, wiersz). Jak się obawiasz wolnego odświeżania, to wywołuj precyzyjna metodę.Ja stosuje bardzo wymyślne wyświetlania i nie zauważyłem żadnego opóźnienia.
  4. Mam wrażenie, że nie rozumiesz jak działa JTable.
0

Spróbuj zamiast implementować TableCellRenderer'a rozszerzyć klasę DefaultTableCellRenderer, która zaimplementowana jest tak, aby zwiększyć wydajność rysowania komórek.
http://docs.oracle.com/javase/6/docs/api/javax/swing/table/DefaultTableCellRenderer.html

0

@bogdans, tworzę tabelę np.

Object data[][] = new Object[4][4]; // ew. zamiast Object - int, string cokolwiek.
String header[] = {"a", "b", "c", "d"};
JTable table = new JTable(data, header);

// I teraz dodaje tabelę, ustawiam jej model, edytowalność itd. W każdym razie wszystkie pola tablicy data[][] są null, nic tam nie ma. Mogę zmienić np. bgColor globalnie dla JTable, ale.. 

..czy mogę zmienić bg dla pojedynczej komórki, która ma określone rozmiary i inne właściwości, ale jest pusta, nie zawiera żadnych obiektów, ani danych? To mnie nurtuje. Bo mogę przecież selektywnie komórki zaznaczać itd, ale szukam możliwości zmiany tła pojedynczej komórki. Pobieram sobie np. index tablicy data[][], który jest przypisany danej komórce, dla której chcę zmienić tło w danym momencie i to robię, ale komórki nie posiadającej żadnego obiektu. O to się cały czas rozchodzi.

1

Ech..., tak jak napisał bogdans, nie rozumiesz jak to działa. Więc po kolei: kiedy JTable chce narysować komórkę o współrzędnych (row, col) najpierw pobierany jest obiekt TableCellRenderer dla kolumny col, a następnie pobierana jest wartość komórki (row, col) poprzez wywołanie metody getValue(...) z modelu (lub odwrotnie, ale to nie ma znaczenia). Następnie jest wywoływana metoda getTableCellRendererComponent z odpowiednio ustawionymi parametrami. Ta metoda zwraca komponent, który zostanie narysowany w miejscu komórki (row, col).
Prześledź poniższy kod, powinien Ci to rozjaśnić. Pamiętaj, że DefaultTableCellRenderer sam dziedziczy po JLabel:

...
Object data[][] = new Object[4][4];
String header[] = {"a", "b", "c", "d"};
JTable table = new JTable(data, header);
		
data[0][3] = 1;
data[3][2] = "aaaa";
data[1][1] = 3;
data[2][0] = 1.111;
	
TableCellRenderer renderer = new MyTableCellRenderer();
		
for (int i = 0; i < table.getColumnCount(); i++) {
	table.getColumnModel().getColumn(i).setCellRenderer(renderer);			
}
...

class MyTableCellRenderer extends DefaultTableCellRenderer {
		
	@Override
	public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
		if (row == 1 && column == 2) { // ustawienie wyglądu w zależności od numeru komórki
			setBackground(Color.LIGHT_GRAY);
		} else {
			setBackground(Color.WHITE);				
		}
			
		if (value == null) { // ustawienie wyglądu w zależności od zawartości koórki
			setBorder(BorderFactory.createLineBorder(Color.RED));
			setText("");
		} else {
			if (value instanceof Integer) {
				setBorder(BorderFactory.createLineBorder(Color.GREEN));					
			} else if (value instanceof Double) {
				setBorder(BorderFactory.createLineBorder(Color.BLUE));
			} else {
				setBorder(BorderFactory.createLineBorder(Color.BLACK));
			}
			setText(value.toString());
		}		
		return this;		
	}	
}
0

To prawda, nie rozumiałem mechaniki. Jednak dzięki Wam JTable odkryło choć część swych sekretów :) Widzę też, że tak czy siak będę miał do czynienia z JLabelami, czego tak bardzo chciałem uniknąć. No cóż, nie pozostaje nic innego jak siadać do czytania i pisania w celu doskonalenia rozumienia mechaniki działania :)

Bardzo wam dziękuję za pomoc w otworzeniu kolejnych drzwi w javie.

Pozdrawiam ciepło :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.