JTable, kolorowe tło w komórkach

Odpowiedz Nowy wątek
2011-09-28 03:31
0

Temat podobny był tutaj:
JTable, kolorowy tekst w komórkach
ale jak w nim napisałem to nie zrobiło go wyżej, więc nikt by nie zauważyć (rocznik wątku: 2007, to już całkiem niezłe wino by było).

Moje uprzejme zapytanie do bazy danych Waszych mózgów:
W linku jest automatycznie formatowana komórka, ale ja chciałbym coś takiego:

jTable1.getCellRender(row, col)/*to jest*/.setBakground(Color c);

Otóż getCellRender zwraca TableCellRenderer, który jest klasą abstrakcyjną, ale tam nie ma metody setBackgound. Jest ona w DefaultTableCellRenderer.

Prubuję coś na ten sposób (wszystkich sposobów, którymi próbowałem się do tego dostać nie jestem w stanie wylistować):

DefaultTableCellRenderer celRenderer = (DefaultTableCellRenderer) myJXTable1.getCellRenderer(selectedRowId, 1);

Ale wyrzuca exceptiona, że nie może rzutować.

Settera na renderer komórki nie ma:-( Na kolumny jest, ale nie na komórki:-(

Dziękuję,
A.

P.S. To jest niefajne, że nie ma settera.


"Ten, de profundis, z ciemnego kurhanu
Na trąbę powstanie. " Juliusz Słowacki

"Polacy! Gdyby Spartanie odżyli i zobaczyli Wasz heroizm i bohaterstwo, waleczny i dzielny ten naród schyliłby przed Wami czoło. Polska nie może być zwyciężona." - J.Bryan

Pozostało 580 znaków

2011-09-28 08:33
bo
0

Ustaw renderera dla kolumny. Wewnątrz renderera sposób rysowania uzależniaj od wiersza.

Pozostało 580 znaków

2011-09-28 10:10
0

Tylko, że nie chcę dla wszystkich wierszy tego zmieniać, ani z żadnego automatu po wartościach. Chcę zmieniać to już po narysowaniu komponentu. Ta kolumna akurat ma mieć wszystkie wartości "". Kolor jej komórek ma być informację dla usera, która będzie się też zmieniać za przyczyną jego działań.


"Ten, de profundis, z ciemnego kurhanu
Na trąbę powstanie. " Juliusz Słowacki

"Polacy! Gdyby Spartanie odżyli i zobaczyli Wasz heroizm i bohaterstwo, waleczny i dzielny ten naród schyliłby przed Wami czoło. Polska nie może być zwyciężona." - J.Bryan

Pozostało 580 znaków

2011-09-28 10:17
bo
1

Dodaj do modelu kolumnę duch, której nie wyświetlasz, wartości w tej kolumnie zależą od działań użytkownika. Kolor wyświetlany w kolumnie Cię interesującej zależy od tego co jest w kolumnie duch.

Pozostało 580 znaków

2011-09-28 10:32
0

Ciekawy pomysł:-) Natchnął mnie.
Zrobię sobie Listę, która będzie przechowywać te dane. Moja tabela to rozszerzenie JXTable, więc nie muszę wiele zmieniać. I tak muszę takie coś zrobić, chciałem to tylko zapamiętywać poziom w hierarchii wyżej.


"Ten, de profundis, z ciemnego kurhanu
Na trąbę powstanie. " Juliusz Słowacki

"Polacy! Gdyby Spartanie odżyli i zobaczyli Wasz heroizm i bohaterstwo, waleczny i dzielny ten naród schyliłby przed Wami czoło. Polska nie może być zwyciężona." - J.Bryan
edytowany 2x, ostatnio: arrowman, 2011-09-28 10:54

Pozostało 580 znaków

2011-09-28 10:56
bo
0

Nie wiem jak to jest w C#, ale działania użytkownika chcesz chyba zapamiętać. Pamiętanie ich przez typ renderera związanego z komórką jest, imo, dziwaczne. Jak nie chcesz modyfikować modelu, to możesz stworzyć dodatkową kolekcję (np. ArrayList) i w niej przechowywać wybory użytkownika. Jeżeli dopuszczasz zmianę uporządkowania na ekranie, to przy synchronizacji modelu z dodatkową kolekcja pamiętaj o użyciu metody convertRowIndexToModel.

Pozostało 580 znaków

2011-09-28 11:36
0

Przecież JTable getCellRender() zwraca obiekt implementujący interfejs TableCellRenderer, a ten w swojej jedynej metodzie TableCellRenderer.getTableCellRendererComponent() zwraca obiekt klasy Component. Component ma już metodę setBackground(Color c).
Problem w tym, że ponieważ renderer jest jeden na całą tablicę, to trzeba by wywoływać tę metodę co jedno odrysowanie komórki przez JTable biorąc pod uwagę jak JTable renderuje swoje komórki (DefaultTableCellRenderer, Implementation Note). Zawsze jednak można użyć metody prepareRenderer() i ustawić dla wybranych lub wszystkich komórek takiego renderatora, który będzie uwzględniał malowanie tła innym kolorem. Można użyć do tego wcześniej wyciągnięty obiekt DefaultTableCellRenderer i zmienić mu po prostu malowanie tła za pomoca setBackground(). Właśnie po to są różne defaultowe klasy obiektów. Nie jestem tylko pewien czy przy wywołaniach dla różnych komórek można użyć tego samego obiektu po modyfikacji dla każdej komórki czy jednak koniecznie całe zmodyfikowane kopie.


Jeżeli ktoś komuś coś, ewentualnie nikt nikomu nic, to właściwie po co...?

Pozostało 580 znaków

2011-09-28 12:25
0
bo napisał(a)

Jak nie chcesz modyfikować modelu, to możesz stworzyć dodatkową kolekcję (np. ArrayList) i w niej przechowywać wybory użytkownika.

Właśnie tak zrobiłem. Ale tu nie chodzi o to, tylko o rysowanie na podstawie tych danych (ArrayList, u mnie Map<Integer, Stack<integer>>).

Olamagato napisał(a)

Przecież JTable getCellRender() zwraca obiekt implementujący interfejs TableCellRenderer,(...)

Właśnie tak zrobiłem, tylko nie działa dla pojedynczych komórek. Oto kod:

public class BackgroundCellRenderer extends DefaultTableCellRenderer {
    private Color fDarkGreen;
    public BackgroundCellRenderer() {super();}

    @Override
    public Component getTableCellRendererComponent(
    JTable aTable, Object aValue, boolean aIsSelected, 
    boolean aHasFocus, int aRow, int aColumn) {  
        Component renderer = super.getTableCellRendererComponent(aTable, aValue, aIsSelected, 
                                                                        aHasFocus, aRow, aColumn);

    MyJXTable table = (MyJXTable)aTable;

    if (table.isSelectedMy(aColumn, aRow)) renderer.setBackground(Color.ORANGE);

    return this;
  }
}

isSelectedMy(aColumn, aRow) sprawdza czy komórka jest na liście, jeżeli tak, ma ją pokolorować.

Oto użycie:

// dodanie do listy komórki.
myJXTable1.addSelectedMy(0, 1);

//  tutaj nadaje nowego rendera
myJXTable1.getColumn(0).setCellRenderer(new BackgroundCellRenderer());

No i mi wyświetla wszystkie komórki na pomarańczowo, a nie pojedyncze
Nie wiem co źle robię:/


"Ten, de profundis, z ciemnego kurhanu
Na trąbę powstanie. " Juliusz Słowacki

"Polacy! Gdyby Spartanie odżyli i zobaczyli Wasz heroizm i bohaterstwo, waleczny i dzielny ten naród schyliłby przed Wami czoło. Polska nie może być zwyciężona." - J.Bryan
edytowany 1x, ostatnio: arrowman, 2011-09-28 12:26

Pozostało 580 znaków

2011-09-28 13:21
bo
0

Jeśli chcesz zmienić kolor tła JLabela, to musisz wywołać metodę setOpaque(true);

    if (table.isSelectedMy(aColumn, aRow)) 
    {
        renderer.setOpaque(true);    
        renderer.setBackground(Color.ORANGE);
    }

Pozostało 580 znaków

2011-09-28 13:33
0
bo napisał(a)

Jeśli chcesz zmienić kolor tła JLabela, to musisz wywołać metodę setOpaque(true);

Kolor się zmienia poprawnie, ale nie dla jednej tylko wszystkich komórek w kolumnie:/
Nie potrafię tego rozgryźć. Przeglądam pełno przykładów na google i nic, robi mi się dla wszystkich.


"Ten, de profundis, z ciemnego kurhanu
Na trąbę powstanie. " Juliusz Słowacki

"Polacy! Gdyby Spartanie odżyli i zobaczyli Wasz heroizm i bohaterstwo, waleczny i dzielny ten naród schyliłby przed Wami czoło. Polska nie może być zwyciężona." - J.Bryan
Między wszystkich, a wszystkich w kolumnie jest spora różnica. Nie ma się co dziwić, że zmienia się dla całej kolumny skoro dokładnie to zaimplementowałeś (getColumn(0)). - Olamagato 2011-09-28 13:56
Też tak mi się wydawało. Tylko ja to zrobiłem na podstawie kodu z jakiejś strony gdzie był przykład i screen do tego. Oni zmieniali co prawda foreground, ale to bez znaczenia. I tam niby było dobrze. Muszę "wychaczyć" dokładnie te rysowanie komórek. - arrowman 2011-09-28 14:15

Pozostało 580 znaków

2011-09-28 13:40
0

Tak jak napisałem, użyj
http://download.oracle.com/ja[...]CellRenderer,%20int,%20int%29

JTable to jeden z najbardziej skomplikowanych obiektów Swinga i można zrobić z nim rzeczy, o których Tobie (oraz mi również) się nie śniło.
Metody TableColumn.setCellRenderer() używa się do czego innego niż ty potrzebujesz. Czasem nawet bardzo uważne przeczytanie dokumentacji jednej klasy nie wystarcza aby zrozumieć wszystkie zależności w tej klasie.
Dla każdej kolumny tworzysz osobny obiekt renderatora, ale przecież nie masz pojęcia w którym momencie zostanie gdzieś w obiekcie JTable wywołana metoda getTableCellRendererComponent(), a tym samym czy użycie w takiej metodzie Twojej specyficznej metody isSelectedMy() ma w ogóle jakikolwiek sens.
Pomijam już to, że zakładanie a priori iż argument aTable jest na pewno Twoją MyJXTable też jest dość ryzykowne bo nie masz pojęcia co się dzieje wewnątrz nieznanego sobie obiektu, niektóre klasy zwracają różne wrappery i inne wynalazki implementujące ten sam interfejs, ale klasy zupełnie innego typu.
Generalnie wyłącz domniemania i uważnie doczytaj dokumentację. W razie potrzeby wrzuć sobie źródła JTable do swojego IDE i prześledź sobie co się dzieje z obiektami renderującymi.

Weź pod uwagę notę implementacyjną do DefaultTableCellRenderer:
"JTable employs a unique mechanism for rendering its cells and therefore requires some slightly modified behavior from its cell renderer. The table class defines a single cell renderer and uses it as a as a rubber-stamp for rendering all cells in the table; it renders the first cell, changes the contents of that cell renderer, shifts the origin to the new location, re-draws it, and so on."

oraz to:
"The standard JLabel component was not designed to be used this way and we want to avoid triggering a revalidate each time the cell is drawn. This would greatly decrease performance because the revalidate message would be passed up the hierarchy of the container to determine whether any other components would be affected. As the renderer is only parented for the lifetime of a painting operation we similarly want to avoid the overhead associated with walking the hierarchy for painting operations. So this class overrides the validate, invalidate, revalidate, repaint, and firePropertyChange methods to be no-ops and override the isOpaque method solely to improve performance. If you write your own renderer, please keep this performance consideration in mind. "

Jak dla mnie to jest to dość dobrze wyjaśnione.


Jeżeli ktoś komuś coś, ewentualnie nikt nikomu nic, to właściwie po co...?
edytowany 3x, ostatnio: Olamagato, 2011-09-28 13:54
Właśnie to czytałem i coś kombinuje, jednak trochę po omacku. Tej mapy ze stosem chyba się nie pozbędę, ale ona nie powinna chyba przeszkadzać (mogę się mylić) w kolorowaniu, w końcu tylko o to mi chodzi. A tej dokumentacji to jest opisane jak to działa, ale mogła by być jeszcze nota gdzie (szczególnie do 1 akapitu). - arrowman 2011-09-28 14:12

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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