Krzysztof Barteczko
Posługiwanie się bardziej złożonymi komponentami Swingu wymaga pojęcia o architekturze ich konstrukcji. Architektura ta nazywa się "Model-View_Controller" i pełni bardzo ważną rolę w działaniu programów swingowych i w takim ich tworzeniu, by były elastyczne, uniwersalne i łatwo modyfikowalne.
Swing bazuje na architekturze "Model-View-Controller" (MVC), przejętej (z modyfikacjami) z języka SmallTalk. W architekturze tej:
· model - określa dane związane z komponentem lub stany komponentu,
· widok (view) - określa wizualną reprezentację danych lub stanów,
· sterownik (controller) - zapewnia interakcję użytkownika z widokiem i wynikające stąd modyfikacje modelu.
Taka separacja umożliwia bardziej elastyczne i logiczne tworzenie kodu, m.in. dzięki skupieniu uwagi na modelu danych, który może następnie być prezentowany przez różne widoki.
W Swingu połączono ze sobą widok i sterownik (View-Controller) w tzw. delegacie UI (od "user interface"). W ten sposób model danych jest odseparowany od komponentu (co umożliwia programowanie w kategoriach modelu), zaś zadania uwidaczniania i interakcji są przez komponent delegowane do odpowiedniego obiektu UI (co daje omawiany już wcześniej konfigurowalny wygląd - "pluggable look and feel").
Prawie wszystkie komponenty Swingu mają swoje modele, realizowane jako interfejsy. Można wyróżnić dwa typy modeli:
· modele GUI - interfejsy definiujące wizualne stany komponentów, np. przycisk wciśnięty lub zaznaczenie elementu na liście,
· modele danych - interfejsy reprezentujące dane takie jak np. wartość komórki w tabeli lub elementu listy
W tabeli pokazano modele dla komponentów Swingu.
Tabela. Modele komponentów Swingu
Komponent
Interfejs modelu
Typ modelu
JButton
ButtonModel
GUI
JToggleButton
GUI/dane
JCheckBox
JRadioButton
JMenu
JMenuItem
JCheckBoxMenuItem
JRadioButtonMenuItem
JComboBox
ComboBoxModel
dane
JProgressBar
BoundedRangeModel
JScrollBar
JSlider
JTabbedPane
SingleSelectionModel
JList
ListModel
ListSelectionModel
JTable
TableModel
TableColumnModel
JTree
TreeModel
TreeSelectionModel
JEditorPane
Document
JTextPane
JTextArea
JTextField
JPasswordField
Źródło: Amy Flower. A Swing Architecture Overview. The Inside Story on JFC Component Design, Swing Connection
Dostęp do modeli zapewniony jest poprzez metody getModel() i setModel(...) w klasach komponentów. Za pomocą metody setModel(...) możemy ustalić własny model. Winien on być obiektem klasy implementującej odpowiedni interfejs modelu. Jeśli nie stworzymy własnego modelu, to każdy z komponentów będzie związany z pewnym modelem domyślnym, zrealizowanym jako klasa, której nazwa zwykle zaczyna się słowem Default (np. DefaultListModel). Po uzyskaniu dostępu do modelu (metodą getModel()) możemy wywoływać metody odpowiedniej klasy implementującej interfejs modelu. W wielu przypadkach w klasach komponentów znajdują się metody, które pośredniczą w takich odwołaniach: są wygodne i pozwalają programować bez świadomości, iż korzysta się z modeli. Np. w klasie JSlider mamy metody, które pozwalają uzyskać i ustalić aktualną wartość pokazywaną przez suwak oraz wartości maksymalne i minimalne. Faktycznie metody te odwołują się do odpowiednich metod modelu typu BoundedRangeValue (np. getValue() z klasy JSlider jest zrealizowana jako getModel().getValue(). Jednak tylko przy prostych komponentach (np. JButton czy JSlider) lub przy prostych programach, korzystających z ograniczonego zakresu możliwości bardziej złożonych komponentów (np. lista, prezentująca stały zestaw wartości) można uniknąć świadomego użycia modeli, co zresztą jest dobrą praktyką programowania.
Swingowa lista (komponent klasy JList) jest dobrym przykładem stopniowego przechodzenia od "bezmodelowego" programowania do programowania, w którym użycie modelu jest nie tylko potrzebne, ale i konieczne.
Lista jest związana z dwoma modelami:
· danych (klasa implementująca interfejs ListModel)
· oraz GUI (implementacja interfejsu ListSelectionModel).
Nie zawsze jednak musimy o tym wi...
Phoob