Creating Interactive GUIs with Swing's MVC Architecture Part 2: Dynamic View for a Static Model
In the first part of this article, "Model-View-Controller and Swing," I described fundamentals of how a Model-View-Controller design pattern is embedded within a Swing toolkit. In this article, I'll show how to create a dynamically adjustable presentation of a corresponding model for a Swing Table UI component. The approach will also rely on inheritance, passing objects by reference, and event/listener mechanisms of the Java language. The final sample code will show a solution to the problem of real-time manipulation of a presentation without altering the model, or requesting data again on every user-invoked event. The technique can easily be adapted to any Swing component.
As I've indicated in my previous articles, MVC has been around for a long time and has been adapted in all sorts of frameworks, ranging from desktop GUIs to Web-based applications. To show how Model-View-Controller is used in the Java Swing toolkit, I've created a simple project with fictional population data on different moons of planets within our solar system. The data is presented in a Swing JTable component and I've included other components in my application as well. See Figure 1. If you are not familiar with Swing or Java AWT frameworks, please see the reference section for online and printed publications and tutorials on these technologies. In this article, I'll assume that you are familiar with some graphical toolkit, and are confident with Java as an object-oriented language, and perhaps have used Swing to create simple GUIs.
The application has a table consisting of Moon name, Planet name (it belongs to), its atmospheric gas name, and population size. The business objective of the UI will be to present the user with data, and let the user manipulate it in any way the user may choose; for instance, to sort based on the moon name or filter by planet. The application must also be fast and not memory intensive. And, it certainly must not require reloading of data or creation of new Model Objects on each user request! The application puts in use all the fundamentals I presented in the first part of this article and also contains an easily adaptable approach to the dynamic manipulation of the presentation. You should be able to apply my models and programming routines to your enterprise GUI application without major changes.
This is a screenshot of an application; the drop-down selection is a filtering mechanism.
To demonstrate visual manipulation of the data, my application has a drop-down menu (JComboBox) and a main table (JTable). The drop-down has a list of planets and serves as a filtering mechanism. the When user selects an entry from the list, the presentation in the table is changed. The table also has a default header, which serves as a sorting mechanism; clicking on any column header name will sort the entire table based on that column, thus also altering presentation. Both sorting and filtering are user requests, resulting in a change of what is displayed on the screen; the underlying data, however, is not changed. This is achieved by getting and keeping data in a model object and then altering how it's shown in a view object. Different user requirements may call for model object(s) with special characteristics; therefore, they have to be custom and either extend or change default model properties of that particular visual component.
As I described in Part 1, all Swing objects follow a separable model architecture, and every visual component has a corresponding model object. In case of JTable, a javax.swing.table.DefaultTableModel object holds all data and defines essential methods on that data.
getValueAt(int row, int col),
setValueAt(int row, int col),
isCellEditable(int row, int col) and many others including event methods.
A JTable object with a default model will let users do a lot, but it won't help with a dynamic change in presentation. In order to accomplish sorting, filtering, and any other operation on the view, a custom model object(s) have to be created. I have a PlanetTableModel object (that inherits everything from the DefaultTableModel), to hold the real data, and in addition several filtering models, PlanetTableSortFilter and PlanetDataExclutionFilter, to help with sorting and filtering tasks.