JTable i dwa razy JScrolPane

0

Witam

Chciałbym wyświetlać tą samą tabele w 2 różnych panelach. Efekt jaki chcę osiągnąć to aby dwie pierwsze kolumny tabeli były zawsze widoczne natomiast pozostałe były scrollowalne.

Pierwszym pomysłem było:

JTable table = ...
JScrollPane scrollPane = new JScrollPane();
scrollPane.setRowHeaderView(table); //szerokosc bym ustawil na 2 pierwsze kolumny
scrollPane.setViewportView(table); //scrollowanie bym ustawil od 3 do ostatniej kolumny

Nie działa (wyświetla tylko drugi ustawiony widok)

Drugim:

JTable table = ...
JScrollPane scrollPaneHeader = new JScrollPane();
JScrollPane scrollPaneCenter = new JScrollPane();
scrollPaneHeader.setViewportView(table); //scrollowanie bym ustawił na 2 pierwsze kolmny
scrollPaneCenter.setViewportView(table); //scrollowanie bym ustawil od 3 do ostatniej kolumny
// + synchronizacja suwaków

Nie działa (wyświetla tablę tylko w drugim JScrollPane)

Trzecim:

//Stworzyć nowa instancję JTable i pobrać model (getModel()) z pierwsze tabeli

Ale tego nie chce mi się robić bo musiałbym dodatkowo zadbać o identyczne sortowania, zaznaczania komórek i pewnie jeszcze jakieś głupoty.

Czy naprawdę nie jest możliwe wyświetlanie tej samej tabeli w dwóch widokach?
Ewentualnie jak szybko, łatwo i przyjemnie rozwiązać mój problem?

Z góry dziękuje za pomoc.

0

Upewniam się czy dobrze rozumiem pytanie. Tabela jest szeroka i nie mieści się na ekranie, pojawił się więc poziomy suwak. Chcesz by niezależnie od położenia suwaka pewne kolumny były cały czas widoczne ?
BTW, napisałeś

Czy naprawdę nie jest możliwe wyświetlanie tej samej tabeli w dwóch widokach?

Przecież tabela to jest widok, więc pytanie imho brzmi

Czy naprawdę nie jest możliwe wyświetlanie tego samego widoku w dwóch widokach?

0

Wydaje mi się, że chcesz uzyskać efekt jaki powstaje gdy w jakimś arkuszu kalkulacyjnym (np. Excelu) podzielisz pionowo okno tak aby w lewym panelu pozostały dwie pierwsze kolumny, a w prawym pozostałe kolumny. Oraz zablokujesz widok.
Tak więc jeżeli o To Ci chodzi, to należy zrobić podobnie. Umieścić obok siebie stykające się dwa widoki tabel. W lewym umieść tylko pierwsze dwie kolumny. Musi mieć on szerokość wystarczającą do pomieszczenia obu początkowych kolumn - gdyby użytkownik poszerzył te kolumny, to lewy widok musi się poszerzyć kosztem zmniejszenia prawego widoku. A prawy widok mający już scrolla mógłby wyświetlać od trzeciej kolumny tabeli danych, tyle widocznych kolumn ile wystarczy miejsca. Oba komponenty mogłyby być rozdzielone przez SplitPane, gdyby użytkownik mógł poszerzać lub zwężać obie lewe kolumny jednocześnie, ale nie musi to być potrzebne.
Moim zdaniem najprościej jest uzyskać taki efekt jakimś visualem (obecnym w prawie każdym IDE) i sprawdzić jaki z tego powstaje kod, a następnie go użyć.

0

Upewniam się czy dobrze rozumiem pytanie.

Tak dokładnie o to chodzi.

Przecież tabela to jest widok, więc pytanie imho brzmi

Jak już się zagłębiać w szczegóły techniczne to nie widok tylko java.awt.Component i java.awt.Container, co gorsze chyba faktycznie nie można wyświetlić tego samego Component'u w dwóch różnych Container'ach - a szkoda. Jeśli jednak jakoś się da to proszę mnie uświadomić jak?

Wydaje mi się, że chcesz uzyskać efekt jaki powstaje gdy w jakimś arkuszu kalkulacyjnym

Tak dokładnie o to chodzi...

Tak więc jeżeli o To Ci chodzi, to należy zrobić podobnie. Umieścić obok siebie stykające się dwa widoki tabel

...ale w ten sposób będą to dwie różne tabele i jak zaznaczę wiersz w pierwszej tabeli to w drugiej tabeli odpowiedni wiersz nie zostanie automatycznie zaznaczony.

Prowizoryczne rozwiązanie

TableModel model = ...
JTable table1 = new JTable(model);
JTable table2 = new JTable(model);
table2.setAutoCreateColumnsFromModel(false);
for(String column : new String[] { "column1", "column2" }) {
 TableColumn tableColumn = table1.getColumn(column);
 table1.removeColumn(tableColumn);
 table2.addColumn(tableColumn);
}
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewPort(table1);
scrollPane.setRowHeaderView(table2);
scrollPane.setCorner(ScrollPaneConstants.UPPER_LEFT_CORNER, table2.getTableHeader());

Powyższy uproszczony przykład faktycznie tworzy dwie różne tabele mające ten sam model. Druga tabela domyślnie nie wyświetla żadnych kolumn tylko dodawane są do niej kolumny usunięte z pierwszej tabeli. Na koniec obie tabele wrzucane są do JScrollPane. Jedna do ViewPort druga do RowHeaderView.

Wygląda i działa to mniej więcej tak jak chciałem ale jest jeden problem. Zaznaczenie komórki zaznacza pojedynczy cały wiersz i przesuwając myszką po table1 scrollbar w scrollPane działa jak powinien natomiast ta sama czynność w table2 nie ma wpływu na scrollbar i wiersze się rozjeżdżają. Da się coś z tym zrobić?

0

Tak więc jeżeli o To Ci chodzi, to należy zrobić podobnie. Umieścić obok siebie stykające się dwa widoki tabel

...ale w ten sposób będą to dwie różne tabele i jak zaznaczę wiersz w pierwszej tabeli to w drugiej tabeli odpowiedni wiersz nie zostanie automatycznie zaznaczony.

Masz rację. Dlatego, żeby to dobrze zrobić musisz zbudować sobie komponent z dwóch istniejących widoków tabel, które musisz w swoim kodzie synchronizować bez względu na to czy focus będzie na lewym widoku czy na prawym.
Oczywiście o ile już ktoś czegoś takiego nie wykombinował lub nie da się uzyskać takiego efektu za pomocą jakichś opcji w istniejących komponentach.

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