Das MVC-Muster ist ein Modell dafür, wie eine Benutzeroberfläche strukturiert werden kann. Daher definiert es die 3 Elemente Modell, Ansicht, Controller:
- Modell Ein Modell ist eine Abstraktion von etwas, das dem Benutzer präsentiert wird. Im Swing haben Sie eine Unterscheidung zwischen GUI-Modellen und Datenmodellen. GUI-Modelle abstrahieren den Status einer UI- Komponente wie ButtonModel . Datenmodelle abstrahieren strukturierte Daten, die die Benutzeroberfläche dem Benutzer wie TableModel präsentiert .
- Ansicht Die Ansicht ist eine UI-Komponente, die für die Darstellung der Daten für den Benutzer verantwortlich ist. Somit ist es für alle UI-abhängigen Probleme wie Layout, Zeichnung usw. verantwortlich, z . B. JTable .
- Controller Ein Controller kapselt den Anwendungscode, der für eine Benutzerinteraktion ausgeführt wird (Mausbewegung, Mausklick, Tastendruck usw.). Controller benötigen möglicherweise Eingaben für ihre Ausführung und erzeugen Ausgaben. Sie lesen ihre Eingaben von Modellen und aktualisieren Modelle als Ergebnis der Ausführung. Sie können auch die Benutzeroberfläche umstrukturieren (z. B. Benutzeroberflächenkomponenten ersetzen oder eine vollständig neue Ansicht anzeigen). Sie dürfen jedoch nichts über die UI-Komponenten wissen, da Sie die Umstrukturierung in einer separaten Schnittstelle kapseln können, die der Controller nur aufruft. Im Swing wird ein Controller normalerweise von einem ActionListener oder einer Action implementiert .
Beispiel
- Rot = Modell
- Grün = Ansicht
- Blau = Controller
Wenn Button
Sie auf klicken, wird das aufgerufen ActionListener
. Das ActionListener
hängt nur von anderen Modellen ab. Es werden einige Modelle als Eingabe und andere als Ergebnis oder Ausgabe verwendet. Es ist wie Methodenargumente und Rückgabewerte. Die Modelle benachrichtigen die Benutzeroberfläche, wenn sie aktualisiert werden. Die Controller-Logik muss also die UI-Komponente nicht kennen. Die Modellobjekte kennen die Benutzeroberfläche nicht. Die Benachrichtigung erfolgt durch ein Beobachtermuster. Somit wissen die Modellobjekte nur, dass es jemanden gibt, der benachrichtigt werden möchte, wenn sich das Modell ändert.
In Java Swing gibt es einige Komponenten, die auch ein Modell und einen Controller implementieren. ZB die javax.swing.Action . Es implementiert ein UI-Modell (Eigenschaften: Aktivierung, kleines Symbol, Name usw.) und ist ein Controller, da es ActionListener erweitert .
Eine ausführliche Erklärung, Beispielanwendung und Quellcode : https://www.link-intersystems.com/blog/2013/07/20/the-mvc-pattern-implemented-with-java-swing/ .
MVC-Grundlagen in weniger als 240 Zeilen:
public class Main {
public static void main(String[] args) {
JFrame mainFrame = new JFrame("MVC example");
mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainFrame.setSize(640, 300);
mainFrame.setLocationRelativeTo(null);
PersonService personService = new PersonServiceMock();
DefaultListModel searchResultListModel = new DefaultListModel();
DefaultListSelectionModel searchResultSelectionModel = new DefaultListSelectionModel();
searchResultSelectionModel
.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
Document searchInput = new PlainDocument();
PersonDetailsAction personDetailsAction = new PersonDetailsAction(
searchResultSelectionModel, searchResultListModel);
personDetailsAction.putValue(Action.NAME, "Person Details");
Action searchPersonAction = new SearchPersonAction(searchInput,
searchResultListModel, personService);
searchPersonAction.putValue(Action.NAME, "Search");
Container contentPane = mainFrame.getContentPane();
JPanel searchInputPanel = new JPanel();
searchInputPanel.setLayout(new BorderLayout());
JTextField searchField = new JTextField(searchInput, null, 0);
searchInputPanel.add(searchField, BorderLayout.CENTER);
searchField.addActionListener(searchPersonAction);
JButton searchButton = new JButton(searchPersonAction);
searchInputPanel.add(searchButton, BorderLayout.EAST);
JList searchResultList = new JList();
searchResultList.setModel(searchResultListModel);
searchResultList.setSelectionModel(searchResultSelectionModel);
JPanel searchResultPanel = new JPanel();
searchResultPanel.setLayout(new BorderLayout());
JScrollPane scrollableSearchResult = new JScrollPane(searchResultList);
searchResultPanel.add(scrollableSearchResult, BorderLayout.CENTER);
JPanel selectionOptionsPanel = new JPanel();
JButton showPersonDetailsButton = new JButton(personDetailsAction);
selectionOptionsPanel.add(showPersonDetailsButton);
contentPane.add(searchInputPanel, BorderLayout.NORTH);
contentPane.add(searchResultPanel, BorderLayout.CENTER);
contentPane.add(selectionOptionsPanel, BorderLayout.SOUTH);
mainFrame.setVisible(true);
}
}
class PersonDetailsAction extends AbstractAction {
private static final long serialVersionUID = -8816163868526676625L;
private ListSelectionModel personSelectionModel;
private DefaultListModel personListModel;
public PersonDetailsAction(ListSelectionModel personSelectionModel,
DefaultListModel personListModel) {
boolean unsupportedSelectionMode = personSelectionModel
.getSelectionMode() != ListSelectionModel.SINGLE_SELECTION;
if (unsupportedSelectionMode) {
throw new IllegalArgumentException(
"PersonDetailAction can only handle single list selections. "
+ "Please set the list selection mode to ListSelectionModel.SINGLE_SELECTION");
}
this.personSelectionModel = personSelectionModel;
this.personListModel = personListModel;
personSelectionModel
.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
ListSelectionModel listSelectionModel = (ListSelectionModel) e
.getSource();
updateEnablement(listSelectionModel);
}
});
updateEnablement(personSelectionModel);
}
public void actionPerformed(ActionEvent e) {
int selectionIndex = personSelectionModel.getMinSelectionIndex();
PersonElementModel personElementModel = (PersonElementModel) personListModel
.get(selectionIndex);
Person person = personElementModel.getPerson();
String personDetials = createPersonDetails(person);
JOptionPane.showMessageDialog(null, personDetials);
}
private String createPersonDetails(Person person) {
return person.getId() + ": " + person.getFirstName() + " "
+ person.getLastName();
}
private void updateEnablement(ListSelectionModel listSelectionModel) {
boolean emptySelection = listSelectionModel.isSelectionEmpty();
setEnabled(!emptySelection);
}
}
class SearchPersonAction extends AbstractAction {
private static final long serialVersionUID = 4083406832930707444L;
private Document searchInput;
private DefaultListModel searchResult;
private PersonService personService;
public SearchPersonAction(Document searchInput,
DefaultListModel searchResult, PersonService personService) {
this.searchInput = searchInput;
this.searchResult = searchResult;
this.personService = personService;
}
public void actionPerformed(ActionEvent e) {
String searchString = getSearchString();
List<Person> matchedPersons = personService.searchPersons(searchString);
searchResult.clear();
for (Person person : matchedPersons) {
Object elementModel = new PersonElementModel(person);
searchResult.addElement(elementModel);
}
}
private String getSearchString() {
try {
return searchInput.getText(0, searchInput.getLength());
} catch (BadLocationException e) {
return null;
}
}
}
class PersonElementModel {
private Person person;
public PersonElementModel(Person person) {
this.person = person;
}
public Person getPerson() {
return person;
}
@Override
public String toString() {
return person.getFirstName() + ", " + person.getLastName();
}
}
interface PersonService {
List<Person> searchPersons(String searchString);
}
class Person {
private int id;
private String firstName;
private String lastName;
public Person(int id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
public int getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
class PersonServiceMock implements PersonService {
private List<Person> personDB;
public PersonServiceMock() {
personDB = new ArrayList<Person>();
personDB.add(new Person(1, "Graham", "Parrish"));
personDB.add(new Person(2, "Daniel", "Hendrix"));
personDB.add(new Person(3, "Rachel", "Holman"));
personDB.add(new Person(4, "Sarah", "Todd"));
personDB.add(new Person(5, "Talon", "Wolf"));
personDB.add(new Person(6, "Josephine", "Dunn"));
personDB.add(new Person(7, "Benjamin", "Hebert"));
personDB.add(new Person(8, "Lacota", "Browning "));
personDB.add(new Person(9, "Sydney", "Ayers"));
personDB.add(new Person(10, "Dustin", "Stephens"));
personDB.add(new Person(11, "Cara", "Moss"));
personDB.add(new Person(12, "Teegan", "Dillard"));
personDB.add(new Person(13, "Dai", "Yates"));
personDB.add(new Person(14, "Nora", "Garza"));
}
public List<Person> searchPersons(String searchString) {
List<Person> matches = new ArrayList<Person>();
if (searchString == null) {
return matches;
}
for (Person person : personDB) {
if (person.getFirstName().contains(searchString)
|| person.getLastName().contains(searchString)) {
matches.add(person);
}
}
return matches;
}
}