|
|
||
Patrick Keegan's BlogDecember 2007 ArchivesQuickly Enclosing Components in a ContainerPosted by pkeegan on December 21, 2007 at 01:05 PM | Permalink | Comments (2)In the first comment on my last post, I was asked why there isn't a separate JPanel generated for both the master and detail views in NetBeans' Java Desktop Application template. In the process of trying to answer that question, I learned a thing or two about the Swing Application Framework and was reminded of a very useful trick in the GUI Builder (the ability to generate a container to surround components that have already been added to the form). I found that the main reason why there is just one panel to serve both the master and detail views is the structure of the org.jdesktop.application.FrameView component. When you generate a master/detail database app using the Java Desktop Application template in NetBeans IDE 6.0, you get a component structure similar to what we ended up with in the ContactMasterDetail app that I wrote about a few days ago. The representation of those components is shown below in a screenshot of the Inspector window.
You'll notice the FrameView component appears as the first node under the root node of the form. If you switch from Design view to Source view and poke around the code, you'll find that the ContactsMasterDetailView class extends FrameView and that the other components get added to this component. I decided to learn more about this class by looking at it's Javadoc, which is bundled with the IDE. So I right-clicked FrameView in the Source Editor and chose Show Javadoc as shown below.
Looking at the Javadoc, I didn't find much about FrameView, but I did noticed that it extends View, which has much more interesting documentation. It turns out that it is a wrapper for some standard elements - a menu bar, tool bar, component, and a status bar, all of which are optional. It seems that the IDE's Java Desktop Application uses three of those (menu bar, component, and status bar) and that the generated mainPanel serves as the "component". So, in the current app, we can't remove mainPanel and replace it with two new panels (at least not without a lot of fuss). But we can put two panels within the main panel and divide the parts of the UI that way. And there is a way we *can* do that without too much fuss - use the Enclose In feature:
Voila! Now the master and detail sections are separately encapsulated on the form, which will make it easier to add other components to the form without disturbing the layout of the existing components. You can also easily provide some visual separation between the two sections. I did the latter by adding some titled borders to both masterPanel and detailPanel (which you can do by selecting the panel in the Inspector window and customizing its border property in the Properties window. My results are below. Not a work of art, but hopefully demonstrative of some of the possibilities at your fingertips.
Some CRUD Master/Detail DetailsPosted by pkeegan on December 19, 2007 at 12:50 PM | Permalink | Comments (10)I haven't had a chance to write a full tutorial on creating a true master/detail view using the NetBeans GUI Builder. Naturally, lots of questions have arisen about it in the meantime, particularly since the IDE's Java Desktop Application template shows things that pretty much beg those questions. For example, if you follow the Building a Java Desktop Database Application, you will encounter something curious in page 4 of the wizard for the Java Desktop Application template. You have the option to display your "detail" as text fields or as a table. But the table option is greyed out. Why is that? The answer is that table vs. text field is not the only difference here. If you select "Textfields", the generated text fields represent columns from the master table. If you select "Table", the a JTable is generated to represent columns from a different database table, which is related to the master table through a foreign key. Since the car database example only has a single table, the "Table" option here is irrelevant. To show how the "Table" option works, let's create a project based on a database that contains two tables. One table will hold people's names. The other table will hold email addresses. "Normalizing" the database in this manner enables the database to scale more efficiently. We can add multiple email addresses for each person without setting a high character limit for the email address column. And we don't need to have any application logic to parse out multiple email addresses that are stored in the same record. So let's get started. First we'll set up the database:
Now that the database is set up, we can use the New Project wizard to help us generate the Master/Detail form.
After you click Finish, code for the application is generated. In the Projects window, you can view the various classes that are generated by expanding the ContactMasterDetail > Source Packages > contactmasterdetail node. In the Source Editor, you can see the visual design for the master/Detail view. The top table is the "master" table, which shows columns from the CONTACTS2008 table. The bottom table is for the detail view, which shows the ADDRESS column from the EMAIL_ADDRESSES2008 table. When a row is selected in the master table, the detail table displays all address records that reference the contact that is selected in the master table. You can run the application (choose Run > Run > Run Main Project) to see the relations between the tables. When you select a contact in the master table, the email addresses for that contact are displayed in the detail table.
However, the application is not quite ready to work yet. You still need to make a few changes to make the creation of new records work correctly. The first problem is that our use of the "identity" construct for the ID column in the CONTACTS2008 table is not reflected in the entity class that was generated for the table. So if we try to use the application to create a new row in the database, an exception occurs because the application tries to assign a value to the ID column when it should just let it be generated automatically. Luckily this is easy to fix. You just need to add one line of code to the Contacts2008 entity class:
The relevant section of code should look like the following screenshot:
With that problem fixed, we should now be able to use the New button in the running application to add a new record to the master table. However, there is still a second problem we have to fix. When creating a new address record, the record does not appear immediately. In order to see the new empty record so that you can edit it, you have to select a different contact and then reselect the contact for which you want to add the address. This is a bug that is a result of the IDE's support for beans binding falling out of synch with the beans binding library, which underwent some late bug fixes. This will be fixed in a post-6.0 IDE release, but for now you have to use this workaround:
Now when we run the application again, we should be able to use the New button below the detail view to add new email addresses for our contacts. That's it for now. I plan to elaborate on this topic more over the next few months (though I'll probably be pretty quiet over the next few weeks as I'm taking some time away from the computer). But in the meantime, please feel free to write in about specific aspects of DB applications you would like me to help you explore. | ||
|
|