Skip to main content

JTable Detail Based on JComboBox Selection

Posted by pkeegan on June 6, 2008 at 9:39 AM PDT

Another question that has come up in the course of my recent postings is how to bind a combo box selection to a JTable's elements (so that the rows of the table are determined by the selected item of the combo box).

Here are some rough steps to mocking up this behavior. These steps assume that you want db connectivity for the app and that you have a db based on the sql script here: http://weblogs.java.net/blog/pkeegan/archive/2008/05/input_on_a_new.html . Be sure to populate the db tables with actual data.

First we'll create the project, entity classes, and the form:

  1. Create a new Java Application project.
  2. Use the Entity Class from Database template in the New File wizard to create entity classes for the Clients and Orders db tables. Leave the Include Related Tables checkbox selected. (A class for the Countries table will also be generated, though we will not use it.)
  3. In the last page of the wizard, be sure to create a persistence unit.
  4. Create a new JFrame.
  5. Add a JComboBox and JTable.

Now we'll create a list of Clients and bind the combo box to that list.

  1. Right-click the combo box and choose Bind -> elements.
  2. Click Import Data to Form and choose the the appropriate db connection and the clients table.

    This step generates the list object.

  3. Make sure clientsList is shown as the binding source and click OK.

At this point, you would might expect to be able to right-click the JTable, select Bind | elements, and bind to the selectedItem property of the combo box. (In fact, you can do this in NetBeans 6.5, and you might even want to try it in the upcoming M1 build). However, in NetBeans 6.1, the code generation for the binding between the JTable elements and the combo box's selectedItem doesn't work as you might expect. The generated code assumes that the selected item is a plain Object, not a Clients object with sub-properties that can be represented by columns. So ColumnBindings code is not generated. You can work around this problem with some manual coding:

  1. Right-click the JTable and choose Customize Code.
  2. *Above* the jScrollPane1.setViewportView(jTable1); line, insert the following code:
    org.jdesktop.beansbinding.ELProperty eLProperty = org.jdesktop.beansbinding.ELProperty.create("${selectedItem.ordersCollection}");
    org.jdesktop.swingbinding.JTableBinding jTableBinding = org.jdesktop.swingbinding.SwingBindings.createJTableBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, jComboBox1, eLProperty, jTable1);
    org.jdesktop.swingbinding.JTableBinding.ColumnBinding columnBinding = jTableBinding.addColumnBinding(org.jdesktop.beansbinding.ELProperty.create("${product}"));
           columnBinding.setColumnName("Product");
           columnBinding.setColumnClass(String.class);
           columnBinding = jTableBinding.addColumnBinding(org.jdesktop.beansbinding.ELProperty.create("${amount}"));
           columnBinding.setColumnName("Amount");
           columnBinding.setColumnClass(Integer.class);
           jTableBinding.setSourceUnreadableValue(null);
           bindingGroup.addBinding(jTableBinding);
           jTableBinding.bind();
  3. Click OK to close the Customize Code dialog box.
  4. Select the table and click the Properties button in the Properties window.
  5. For the model property, click the ellipsis (...) button to open the property editor.
  6. Click Reset to Default. This removes the superfluous table model that is generated when you add the table to the form but which is rendered obsolete by the binding code you have just added.

When you run the application, the JTable should respond to the selection in the combo box, as shown below.

comboToTable.png

You still need to write a custom renderer for the JTable so that it shows human-relevant text (such as the name of one of the table columns). That task is covered here: http://weblogs.java.net/blog/pkeegan/archive/2007/10/binding_jcombob.html

Comments

Thanks for the feedback everyone! Some quick attempts at answers! Regarding the merging of tables, I'm not sure exactly what you mean. But it is possible to display data from different database tables in the same JTable. For example, if you have two tables related by a foreign key, you can right-click the JTable, choose Table Contents, and then select Columns. Within that view, you can add columns and then bind them with EL expressions to columns of either of the related db tables. Regarding the modifying the generated code to have multiple detail tables, there is no direct way to modify the generated code. But you can get creative with the copy and pasting of generated code. Regarding checks on user input, you can write a custom input verifier and specify this input verifier in the component's input verifier property (much as you do with cell renderers that I mentioned in earlier posts. I cover some of these topics in my upcoming tutorial, which is more or less an expansion of many of the themes I've covered in the last month. I hope to post a draft in the next few days. Stay tuned!

Hi Patrick, I want to let you know that I love your tutorial, which I followed thru' and it works. I've leant alot from this tutorial series, I could not thank you enough! Well done! Okay, I've a doubt that kept me wondering for quite some time, Netbeans generates application for "One master against One detail" model, but if we need to tackle One master and Multiple detail tables, is there an easy way to modify the auto-generated codes?

Hello Patrick Keegan

It worked very intelligent.. help me

I am Willan Jara Cuenca-Ecuador
In my database for Mysql I genereran in CRUD Netbeans6.1 in all tables except Table Establecimientos `I` which generates a class EstablecimientosPK that the same will not let me modify ,insert and delete data

How do I use Netbenas 6.1 or that the code attached to establishments in CRUD?

Create table `TIPO_ESTABLECIMIENTO` (
`ID_TIP_EST` Int NOT NULL AUTO_INCREMENT,
`SUB_TIP_EST` Int,
`TIP_EST_NOMBRE` Varchar(50) NOT NULL,
`TIP_EST_DESCRIPCION` Varchar(255),
Primary Key (`ID_TIP_EST`)
) ENGINE = InnoDB;

Create table `CATEGORIAS` (
`ID_CATEGORIA` Int NOT NULL AUTO_INCREMENT,
`SUB_CATEGORIA` Int,
`CAT_NOMBRE` Varchar(100) NOT NULL,
`CAT_DESCRIPCION` Varchar(255),
Primary Key (`ID_CATEGORIA`)
) ENGINE = InnoDB;

Create table `LUGARES` (
`ID_LUGAR` Int NOT NULL AUTO_INCREMENT,
`SUB_LUGAR` Int,
`LUG_NOMBRE` Varchar(50) NOT NULL,
`LUG_DESCRIPCION` Varchar(45),
Primary Key (`ID_LUGAR`)
) ENGINE = InnoDB
COMMENT = 'PROCEDENCIA YA SEA PAIS, PROVINCIA, CANTON, PARROQUIA, ECT';

Create table `PERSONAS` (
`ID_PERSONA` bigInt NOT NULL AUTO_INCREMENT,
`PER_CEDULA` Char(11),
`PER_APELLIDO_PATERNO` Varchar(35),
`PER_APELLIDO_MATERNO` Varchar(35),
`PER_NOMBRES` Varchar(45),
`PER_FECHA_NACIMIENTO` Date COMMENT 'FECHA DE NACIMIENTO DE LA PERSONA',
`PER_TELEFONO` Varchar(15),
`PER_TELEFONO1` Varchar(15),
`PER_DIRECCION` Varchar(255) COMMENT 'DIRECCION DE LA PERSONA',
Primary Key (`ID_PERSONA`)
) ENGINE = InnoDB;


Create table `ESTABLECIMIENTOS` (
`ID_ESTABLECIMIENTO` Int NOT NULL AUTO_INCREMENT,
`ID_TIP_EST` Int NOT NULL,
`ID_CATEGORIA` Int NOT NULL,
`ID_LUGAR` Int NOT NULL,
`EST_RAZON_SOCIAL` Varchar(45) NOT NULL,
`EST_DIRECCION` Varchar(255) NOT NULL,
`EST_RUC` Varchar(15) NOT NULL,
`EST_TELEFONO` Varchar(15),
`EST_TELEFONO1` Varchar(15),
`EST_LONGITUT` Varchar(20),
`EST_LATITUD` Varchar(20),
`EST_IMAGEN` Varchar(100),
`EST_DESCRIPCION` Varchar(255),
Primary Key (`ID_ESTABLECIMIENTO`,`ID_TIP_EST`,`ID_CATEGORIA`,`ID_LUGAR`),
Constraint `PK_TIP_EST` Foreign Key (`ID_TIP_EST`) references `TIPO_ESTABLECIMIENTO` (`ID_TIP_EST`) on delete restrict on update restrict,
Constraint `PK_EST_CAT` Foreign Key (`ID_CATEGORIA`) references `CATEGORIAS` (`ID_CATEGORIA`) on delete restrict on update restrict,
Constraint `PK_LUGAR_EST` Foreign Key (`ID_LUGAR`) references `LUGARES` (`ID_LUGAR`) on delete restrict on update restrict
) ENGINE = InnoDB;


Create table `PERMISOS` (
`ID_PERMISO` Int NOT NULL AUTO_INCREMENT,
`ID_ESTABLECIMIENTO` Int NOT NULL,
`ID_CATEGORIA` Int,
`ID_TIP_EST` Int NOT NULL,
`PER_CODIGO` Varchar(20) NOT NULL,
`PER_NUMERO` Varchar(20) NOT NULL,
`PER_TAZA` Double(6,2) NOT NULL,
`PER_FECHA` Date NOT NULL,
Primary Key (`ID_PERMISO`),
Constraint `PK_EST_PER` Foreign Key (`ID_ESTABLECIMIENTO`,`ID_TIP_EST`,`ID_CATEGORIA`) references `ESTABLECIMIENTOS` (`ID_ESTABLECIMIENTO`,`ID_TIP_EST`,`ID_CATEGORIA`) on delete restrict on update restrict
) ENGINE = InnoDB;

Please Write... jarwilsis@yahoo.es

Patrick, could you kindly illustrate how to include exception handling, for example, assuming that the First Name must be unique, so when data for a new client record has been entered with a First Name that already exist, then when the Save button is pressed, the system should pop-up an alert message to reject the action to save record with duplicated First Name.

I've followed & done this tutorial. Thanks a lot for this examples, it'd be so useful. Now, I have a question, how would we build an application with 2 relationed tables? I wanna mean, is it posible merge 2 database tables when I use bind on a JTable? Thanks. See ya!!!