Skip to main content

De-modalizing the Customer Records App

Posted by pkeegan on August 7, 2008 at 10:02 AM PDT

I'm back from vacation and (almost) back up to speed, so it's time to resume with my semi-regular posting. Soon, I'd like to show an example of a many-to-many relationship and other examples with joins. But in this post, I'll address a question from Istr that he submitted as a comment to my last post - how to add Next and Previous buttons to the application created in this Java desktop application. That's a pretty reasonable request, given that someone who is doing heavy editing of records might not want to have to go through the trouble of closing the dialog, selecting the next record, etc.

However, for several reasons, it is hard to add the Next/Previous functionality to the dialog itself. Currently, the dialog is passed the current record when it is instantiated, but this is a very one-way transaction. There is no simple way for the dialog to get information on other records. The list object that contains the database records is static and can not be referenced from a non-static method in the dialog. In addition, the transaction logic is in the main view.

The easiest way to add Previous/Next functionality (and probably the best approach from a design point of view) is to redesign the application so that the editable fields are in the main view and directly to the corresponding properties in the master table. You can then add Previous and Next buttons that change the selected record in the master table (and thus also in the text fields because they are bound to the table properties).

One other consideration is how data is saved and how changes are canceled. In the original application, data can only be added or changed for one record at a time, and you have save or cancel those changes to exit the dialog. This design decision is partially based on the assumption that the database will eventually be huge and a person wouldn't go through the records one by one to update them. But for a design where you anticipate wanting to go through many different records, it might be more desirable to save more at once, so that's what we will do here.

You can manage these changes to the application relatively quickly through the following steps:

  1. Download the CustomerRecords application zip file (the application that results from the Creating a Custom Java Desktop Database Application tutorial).
  2. Unzip the file.
  3. In NetBeans 6.0 or 6.1, Choose File | Open Project and navigate to the project folder to open the project.
  4. Open the CustomerEditor class in Design view.
  5. In the Inspector, select all of the components (with the exception of the Save and Cancel buttons).
  6. Right-click and choose Enclose In | Panel.
  7. Right-click the new panel and choose Copy.
  8. Open the CustomerRecordsView class in Design view.
  9. Right-click in the design area and choose Paste.
  10. Drag the panel to the right of the Customers table so that the form widens.
  11. Bind the text fields to the corresponding properties of masterTable.selectedElement.
  12. Drag the CountryCellListRenderer to the form and assign the renderer to the Country combo box (using the Advanced tab of the Bind dialog box).
  13. Add Previous and Next buttons.
  14. Right-click the Previous button and choose Events | Action | actionPerformed.
  15. In the body of the event handler, type or paste the following code:
    if(masterTable.getSelectedRow() > 0)
        masterTable.getSelectionModel().setSelectionInterval(masterTable.getSelectionModel().getMinSelectionIndex() - 1, masterTable.getSelectionModel().getMinSelectionIndex() - 1);      
  16. Right-click the Next button and choose Events | Action | actionPerformed.
  17. In the body of the event handler, type or paste the following code:
    if(masterTable.getSelectedRow() + 1 <  masterTable.getRowCount())
        masterTable.getSelectionModel().setSelectionInterval(masterTable.getSelectionModel().getMinSelectionIndex() + 1, masterTable.getSelectionModel().getMinSelectionIndex() + 1);

Optionally, you can also do the following things to polish the application:

  • Remove the Edit Customer button.
  • Change the New Customer button so that it does not open up a new dialog box (delete the methods in the below the setSaveNeeded(true); statement in the newRecord method).
  • Set minimum widths for the columns of interest (e.g. First Name and Last Name) in the customer table so that you can better browse them. To do so, right-click the customer table, choose Table Contents, and select the Columns tab. You can also remove columns from the table, though doing so would mean that the search wouldn't work for values in those columns.
  • In the refresh() action, call setText("") each of the various text fields so the text fields do not remain populated. (This does not affect any records, because no records are selected after the refresh() action runs.

Once you done with the design changes, you main form might look something like the following screenshot.

next-preview.png

When you run the application, you should be able to press the Preview and Next buttons and see the selection change in the table and the corresponding text fields and combo box.

Comments

Hi Patrick, Got no problem with modalizing except the combo box generate java.lang.ClassCastException. I set ComboBox->Bind->Elements to Countrylist, null and ComnoBox->Bind->SelectedItem to masterTable, ${selectedElement.countryId.CountryId} Did I miss something

dear patrick, I'm new in java specialy netbeans, i was tried your application framework for customer records apps, i ask u how to add the JInternal frame or JPanel or others into JMenuItem action, coz u gave me sample in jdialog....., Sorry if my English is bad, coz i'm Indonesian, thanxs,

dear patrick, I'm new in java specialy netbeans, i was tried your application framework for customer records apps, i ask u how to add the JInternal frame or JPanel or others into JMenuItem action, coz u gave me sample in jdialog....., Sorry if my English is bad, coz i'm Indonesian, thanxs,

Hello Patrick, Thanks for clarifying the next/previous situation. Very helpful! By the way, I tried EditClient using JFrame instead of JDialog and save() doesn't work. Does it only work for JDialog? Thanks in advance

Hi Patrick! I'm a Informatic Engineer Student, and I'm doing me final project about a hotel desktop application. I'm following your tutorial couse is perfect for my project. But I have a doubt, I explain you: I need a bigger application and my problem is that I can't to add a other views like "RoomRecordView.java", "seasonRecordView.java" or "RoomTypeRecodView.java", etc. I do not have any problem If I do diferents projects, becouse netbeans provide my all that I need. But how can I join all this diferents projects? It means how can I do a "main.java" class for controll the others views? I have tryed to use your "CustomerRecordView.java" like a main class, and access to all diferents views from it. And I have obtained to see the tables values in a JTable, but I can't do a new records or refresh, etc. My question is: How can I do a main class? or how can I do for add more views? I need to use a JDialogs?? I hope that the question are clear, because my English is a little poor like my java!!!XD!! thank you very much in advance.

Hi patrick, i've been following your tutorial on "creating a custom java desktop database application." i want to do something with the refresh() task. the problem i had with it is that when you call the refresh() method, the tables are cleared (of its selections). i am attempting to do a refresh action and at the same time, retain the selection on the master table. on the RefreshTask method on the CustomerRecordsView class i tried to replace the following code: list.clear(); list.addAll(data); with: int tempIndex = masterTable.getSelectionModel().getMinSelectionIndex(); list.clear(); list.addAll(data); masterTable.getSelectionModel().setSelectionInterval(tempIndex, tempIndex); when i run the application, it worked out almost fine except that it throws an exception: Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException. Can you help me work around the exception? or if there is another, more elegant workaround with this exception? Any suggestion would be greatly appreciated. Thanks John, Manila

Hey Patrick. You have done an exceptional job of explaining Beans-binding and I commend you on your lucidity. I wonder if you have some insights into a little issue I have been struggling with... I have 2 Entities that persist to the back-end: Company and Contact. Now I have a drop down that allows the user to select a company - thanx to your brilliant Data-Binding explanations. But I now need to dynamically re-populate a second drop-down(combobox) with contacts pertaining to a particular company. The JPQL query should look something like this: String query = "SELECT c FROM Contacts c WHERE c.companycode = " + 12; I tried implementing the above query by getting the company code from the index of the first combobox(company). But for some reason the JPQL query returns ALL of the contacts - not only the contacts at companycode 12 (for example). Any ideas?