craftleft.gif (3002 bytes)QuickTable
Home | API | Tutorial | Download | Support | Contact topblack.gif (108 bytes)
topcurve.gif (60 bytes)
Tutorial
Setup

Basic Table

Existing Connection

Add/Modify/Delete

 

Use wizard to configure Quicktable, less programming required!
Advanced quickTable Example

import javax.swing.*;
import java.sql.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;

public class CustomerOrderDemo extends JFrame implements ActionListener
{
  DBTable dBTable1;
  JButton printButton;
  JButton previewButton;
  JButton findButton;
  JButton replaceButton;
  JButton refreshButton;
  JComboBox skinCombo;
  JComboBox columnCombo;
  JComboBox selectionCombo;
  JTextField  filterText;
  JButton filterButton ;
  JLabel filterLabel;
  JCheckBox filterCheckbox;

  OrderModel myCellModel = new OrderModel();
  MyChangeListener myChangeListener = new MyChangeListener();
  MyCellListener myCellListener = new MyCellListener();
  MyErrorListener  myErrorListener = new MyErrorListener();
  OrderPrintProperties printProp = new OrderPrintProperties();

  Random randomOrderNumber = new Random();

  public CustomerOrderDemo()
  {
    //set Frame properties
    setSize(750,500);
    setName("Customer Order");

    //create a new quicktable
    dBTable1 = new DBTable();

    //add to frame
    getContentPane().add(dBTable1, BorderLayout.CENTER);

    //to create the navigation bars for the table
    dBTable1.createControlPanel();

    try
    {
      //set database properties
      //simple text driver is just a sample implementation, this driver is not
      //production ready, so don't use in your projects
      dBTable1.connectDatabase("jdbc.SimpleText.SimpleTextDriver",
                               "jdbc:SimpleText:" + System.getProperty("user.dir") + java.io.File.separatorChar + "database",
                               "" ,"");

      //To get the jdbc logs, remove the following comment
      //DriverManager.setLogStream(System.out);

      //to get the debug messages for quicktable, uncomment
      //dBTable1.debug = true;

    }
    catch(SQLException e)
    {
      e.printStackTrace();
    }
    catch(ClassNotFoundException e)
    {
      e.printStackTrace();
    }

    //allows users to press Ctrl-c to copy to excel
    //and press ctrl-p to paste the data copied from excel
    dBTable1.enableExcelCopyPaste();

    //create a toolbar for this frame with all the buttons to print,search,skin,filter etc
    createToolBar();

    //this method sets the queries, column properties and calls refresh() for order information
    showOrders();

    setVisible(true);
  }


  public void actionPerformed(ActionEvent e)
  {
    if( e.getSource() == printButton)
    {
      //print the contents in quicktable using the printProperties
      dBTable1.print(printProp);
    }
    else if( e.getSource() == previewButton)
    {
      //show the print preview window using the given printProperties
      dBTable1.printPreview(printProp);
    }
    else if( e.getSource() == findButton)
    {
      //show the find window to search
      dBTable1.doFind();
    }
    else if( e.getSource() == replaceButton)
    {
      //show the find and replace window
      dBTable1.doFindAndReplace();
    }
    else if( e.getSource() == refreshButton)
    {
      //execute the current query again & refresh the data
      try
      {
         //fetch the data from database to fill the table
         dBTable1.refresh();
      }
      catch(SQLException ex)
      {
        ex.printStackTrace();
      }
    }
    else if( e.getSource() == skinCombo)
    {
      //based on the user selection set the Skin
      String selection = (String)skinCombo.getSelectedItem();

      if(selection.equals("Simple"))
      {
        dBTable1.setSkin(new SimpleSkin());
      }
      else if(selection.equals("Cool"))
      {
        dBTable1.setSkin(new CoolSkin());
      }
      else if(selection.equals("Pulse"))
      {
        dBTable1.setSkin(new PulseSkin());
      }
      else
      {
        dBTable1.setSkin(null);
      }
    }
    else if( e.getSource() == selectionCombo)
    {
      //based on user selection show the respective data
      if(selectionCombo.getSelectedItem().equals("Order"))
      {
        showOrders();
      }
      else if(selectionCombo.getSelectedItem().equals("Product"))
      {
        showProducts();
      }
      else if(selectionCombo.getSelectedItem().equals("Customer"))
      {
        //showCustomer();
        //showHTTPCustomer();
        showEJBCustomer();

      }

      //set the first columns name to the filter label
      filterLabel.setText("Find " + dBTable1.getColumn(0).getColumnName());

    }
    else if( e.getSource() == filterButton )
    {
       String filterString = filterText.getText();

       //if the user has entered any valid filter text
       if( filterString != null && !("".equals(filterString)) )
       {
         //search the first column , for the filter text
         dBTable1.filter(0, DBTable.EQUAL , filterText.getText());
       }
       else
       {
         //show all the records without filtering
         dBTable1.filter(null);
       }
    }
    else if( e.getSource() == filterCheckbox )
    {
       //once this checkbox is selected, we show all the records
       //whose first column has an odd number
       if( filterCheckbox.isSelected())
         dBTable1.filter(new OddFilter());
       else
         dBTable1.filter(null);

    }

  }

  public void showOrders()
  {
    //remove all the different settings which is used by products/customer query
    //this removes UpdateSql,InsertSql,DeleteSql,ErrorListener,CellListener,ChangeListener,cellPropertiesModel,Comparator
    dBTable1.clearAllSettings();

    try
    {
      // set the select sql to get data from the order table
      dBTable1.setSelectSql("SELECT Order_Number,Company_Name,Amount,Payment_Type,Paid,In_Stock,Delivery_Type,Status, Client_IP, Order_Date,file  from order");

      //update the changes based on order number
      dBTable1.addUpdateSql("update order set Amount=?,Payment_Type=?,Paid=?,In_Stock=?,Delivery_Type=?,Status=?, Client_IP=?, Order_Date=?, file=? where Order_Number=?","3,4,5,6,7,8,9,10,11,1");

      //Add the insert statements
      dBTable1.addInsertSql("insert into order (Order_Number,Company_Name,Amount,Payment_Type,Paid,In_Stock,Delivery_Type,Status, Client_IP,Order_Date,file) values (?,?,?,?,?,?,?,?,?,?,?)", "1,2,3,4,5,6,7,8,9,10,11");

      //Add delete statements
      dBTable1.addDeleteSql("delete from order where Order_Number = ?", "1");

      //before setting column properties, create the column model for table based on query
      //you can also call refresh() method first and then set column properties
      //but this is a cleaner approach
      dBTable1.createColumnModelFromQuery();

      //set the properties for individual columns
      //although all these properties are automatically generated from database properties
      //its always better to set these properties, since most jdbc drivers don't give
      //the correct meta data


      //we want the first column to be a numeric column , where the maximum length of the
      //number should be 7 digits and we don't want users to edit this cell since this is
      //a primary key
       Column c = dBTable1.getColumn(0);
       c.setReadOnly(true);
       c.setType(Types.NUMERIC);
       c.setPrecision(7);
       //we want the column header of this column to be "Order No". In this header we want the
       //"Order" to be in first line & "No." to be in second line. To get this we have to separate
       //the Order & No. by a newline character
       c.setHeaderValue("Order\nNo.");
       //we want the display width of the column to be 60 (this is not the maximum data length)
       c.setPreferredWidth(60);


       //in the secind column we want to display images, instead of the actual data in database
       //if the database data is "amazon", we want to display amazon.gif , similarly other images
       //so we create a hashtable with the keys being the data in database & the values being the
       //corresponding ImageIcon of the image
       c = dBTable1.getColumn(1);
       c.setReadOnly(false);
       c.setHeaderValue("Company");
       c.setPreferredWidth(139);
       Hashtable imageHash = new Hashtable();
       imageHash.put("amazon",new ImageIcon(this.getClass().getResource("/images/amazon.gif")));
       imageHash.put("barnes",new ImageIcon(this.getClass().getResource("/images/barnes.gif")));
       imageHash.put("compaq",new ImageIcon(this.getClass().getResource("/images/compaq.gif")));
       imageHash.put("eddie",new ImageIcon(this.getClass().getResource("/images/eddie.gif")));
       imageHash.put("flowers",new ImageIcon(this.getClass().getResource("/images/flowers.gif")));
       dBTable1.setCellComponent(c,Column.IMAGE_CELL,imageHash);


       //the third column is going to hold a Double data of the type 653623.23
       //for this number, scale will be the number of digits after the "."
       //and precision will be the total number of digits after
       //the "." and before the "."
       c = dBTable1.getColumn(2);
       c.setReadOnly(false);
       //most jdbc drivers don't give the precision & scale correctly
       //so don't forget to set them
       c.setType(Types.DOUBLE);
       c.setPrecision(10);
       c.setScale(2);
       //we don't want users to enter the negative(-) or postive (+) sign
       c.setSigned(false);
       c.setPreferredWidth(70);


       c = dBTable1.getColumn(3);
       c.setReadOnly(false);
       c.setHeaderValue("Payment\nType");
       c.setPreferredWidth(60);
       Hashtable h = new Hashtable();
       h.put("V",new ImageIcon(this.getClass().getResource("/images/visa.gif")));
       h.put("A",new ImageIcon(this.getClass().getResource("/images/american.gif")));
       h.put("M",new ImageIcon(this.getClass().getResource("/images/master.gif")));
       dBTable1.setCellComponent(c,Column.IMAGE_CELL,h);


       //we want the fifth column to be a checkbox column. whenever the database
       //value id "Y" , we want the checkbox to be checked and when the database value
       //if "N", we want the checkbox not to be checked. For this, we have to create
       //a hashtable mapping these database data to the actual checked or unchecked
       //case. To make it checked, set "new Boolean(true)", for not checked, set "new Boolean(false)"
       c = dBTable1.getColumn(4);
       c.setPreferredWidth(60);
       h = new Hashtable();
       h.put("Y", new Boolean(true));
       h.put("N", new Boolean(false));
       dBTable1.setCellComponent(c,Column.CHECKBOX_CELL,h);


       //we want the sixth column to be a radioButton column. whenever the database
       //value id "Y" , we want the radiobutton to be selected and when the database value
       //if "N", we want the radiobutton not to be selected. For this, we have to create
       //a hashtable mapping these database data to the actual selected or not selected
       //case. To make it selected, set "new Boolean(true)", for not selected, set "new Boolean(false)"
       c = dBTable1.getColumn(5);
       c.setPreferredWidth(60);
       h = new Hashtable();
       h.put("Y", new Boolean(true));
       h.put("N", new Boolean(false));
       dBTable1.setCellComponent(c,Column.RADIOBUTTON_CELL,h);

       //In the seventh column, we don't want user to enter any data, we want the user to enter only
       //the valid values for this column "F" or "U". So when the user tries to edit this cell, we can show
       //a combo box and ask the user to select one of "F" or "U". Again, the database values "F" and "U" are
       //cryptic, we want to show the user a meaningful data "Fedex" or "UPS"
       c = dBTable1.getColumn(6);
       c.setPreferredWidth(60);
       c.setNullable(true);
       h = new Hashtable();
       h.put("F","Fedex");
       h.put("U","UPS");
       dBTable1.setCellComponent(c,Column.COMBOBOX_CELL,h);

       //this eighth column is similar to seventh, but instead of, we hardcoding the possible cell values in
       //the java code, we want to query the database & get the values
       c = dBTable1.getColumn(7);
       c.setBoundSql("select status from shipment_type");
       c.setPreferredWidth(80);

       //in the ninth column, we want the user to enter an ip address
       //but want to make sure , user enters the IP address in correct format
       //Java has a interface javax.swing.text.Document , which can validate the text
       //which a user enters into a textfield. To make sure the user enters the
       //correct IP format, we create a IPDocument class which implements Document
       //and assign that to this column
       c = dBTable1.getColumn(8);
       c.setDocument(new IPDocument());
       c.setPreferredWidth(100);

      //tenth column is a varchar column in datbase which stores date information
      //Still we want to use this
      //column like a Date type column in quicktable, so that the users can use the calendar bean to
      //to select a date instead of typing directly. To implement this we have to create a DataMap object
      //which does this conversion and the set that to this column
       c = dBTable1.getColumn(9);
       c.setHeaderValue("Date");
       c.setDataMap(new DateStringMap());
       c.setType(java.sql.Types.DATE);
       c.setDateFormat("MM/dd/yyyy");
       c.setPreferredWidth(80);

       //this column stores system file information, we want the user to enter a valid
       //file path. Instead of allowing user to type the file path, when the user
       //tries to edit the cell, we want to show a file dialog and get the the file path
       //For this we have to create a class which implements the Cell component and set
       //it through setUserCellEditor
       c = dBTable1.getColumn(10);
       c.setUserCellEditor(new FileCell());
       c.setPreferredWidth(120);

       //to hide a column
       //c.setVisible(false);


      //if we don't want quicktable to handle all the errors
      //and if we want to show meaning full error messages to user
      //then we have to listen for error and show correct error messages
      dBTable1.addDBTableErrorListener(myErrorListener);

      //whenever user changes a cell data, if you want to do some validation
      //add this listener
      dBTable1.addTableCellListener(myCellListener);

      //Whenever a user tries to delete a record, we want to ask the user whether
      //he really wants to delete the record and once the record is delete, we
      //want to tell the user that this record is successfully deleted
      //to implement this we have to add a DatabaseChangeListener to quicktable
      dBTable1.addDatabaseChangeListener(myChangeListener);


       JTable jt = dBTable1.getTable();
       jt.setRowHeight(30);

      //to set the cell alignment, color, font
      dBTable1.setCellPropertiesModel(myCellModel);

       //fetch the data from database to fill the table
       dBTable1.refresh();

    }
    catch(SQLException e)
    {
      e.printStackTrace();
      System.out.println("Warning: This error may be due to a problem in simpletext driver which corrupts the database file during update/insert. Usually it complains \"Invalid Data format\". When you get this error copy all the files under backupdatabase to database directory and overwrite all files, then restart again");
      System.out.println("This error is not due to quicktable , but due to the simple text jdbc driver");
      JOptionPane.showMessageDialog(this,"Database file corrupted, copy all database files from backupdatabase to database directory");
    }
  }


  public void showProducts()
  {

    //remove all the different settings which is used by order/customer
    //this removes UpdateSql,InsertSql,DeleteSql,ErrorListener,CellListener,ChangeListener,cellPropertiesModel,Comparator
    dBTable1.clearAllSettings();

    try
    {
      // set the select sql to get data from the product table
      dBTable1.setSelectSql("SELECT * from Product");

      //update the changes based on product number
      dBTable1.addUpdateSql("update Product set Product_Name=? where Product_Number=?","2,1");

      //Add the insert statements
      dBTable1.addInsertSql("insert into Product (Product_Number,Product_Name) values (?,?)", "1,2");

      //Add delete statements
      dBTable1.addDeleteSql("delete from Product where Product_Number = ?", "1");

       //fetch the data from database to fill the table
       dBTable1.refresh();

    }
    catch(SQLException e)
    {
      e.printStackTrace();
    }

  }

  public void showCustomer()
  {
    //remove all the different settings which is used by order/products
    //this removes UpdateSql,InsertSql,DeleteSql,ErrorListener,CellListener,ChangeListener,cellPropertiesModel,Comparator
    dBTable1.clearAllSettings();

     //we want to load a comma delimtied customer file
     File customerFile = new File("customer.SDF");
     Properties prop = new Properties();

     //set the comma to be the delimiter
     prop.put("delimiter",",");

     //firstRowHasColumnNames is an optional parameter, if first row doesn't have columns
     //don't add this property at all
     prop.put("firstRowHasColumnNames","true");

     try
     {
       dBTable1.refresh(customerFile,prop);
     }
     catch(Exception e)
     {
       JOptionPane.showMessageDialog( this,"Error loading " + customerFile.getPath() + " " + e.getMessage(),"",JOptionPane.OK_OPTION);
     }
  }


  public void showHTTPCustomer()
  {
    //remove all the different settings which is used by order/products
    //this removes UpdateSql,InsertSql,DeleteSql,ErrorListener,CellListener,ChangeListener,cellPropertiesModel,Comparator
    dBTable1.clearAllSettings();

     java.net.URL customerUrl = null;

     //if you are within firewall, don't forget to set the proxy settings as below
     //for http:
     //System.setProperty("http.proxyHost", proxyUrl);
     //System.setProperty("http.proxyPort", proxyPort);

     //for https
     //System.setProperty("https.proxyHost", proxyUrl);
     //System.setProperty("https.proxyPort", proxyPort);

     //we want to load a comma delimtied customer file
     try{
       customerUrl = new java.net.URL("http://quicktable.org/customer.SDF");
     }catch(Exception e){}

     Properties prop = new Properties();

     //set the comma to be the delimiter
     prop.put("delimiter",",");

     //firstRowHasColumnNames is an optional parameter, if first row doesn't have columns
     //don't add this property at all
     prop.put("firstRowHasColumnNames","true");

     //if the url is protected by basic authentication, add the username, password
     //prop.put("username","quicktable");
     //prop.put("password","quicktable");

     try
     {
       dBTable1.refresh(customerUrl,prop);
     }
     catch(Exception e)
     {
       JOptionPane.showMessageDialog( this,"Error loading " + e.getMessage(),"",JOptionPane.OK_OPTION);
     }
  }

  //This will be useful during using EJB/rmi/corba/java objects, where you don't have direct
  //access to database
  public void showEJBCustomer()
  {
    //remove all the different settings which is used by order/products
    //this removes UpdateSql,InsertSql,DeleteSql,ErrorListener,CellListener,ChangeListener,cellPropertiesModel,Comparator
    dBTable1.clearAllSettings();

    //usually through EJB, while using findXXX method, it will return a enumeration/collection of objects
    //to simulate that setup we are going to create enumeration of object first

    Vector v = new Vector();
    v.addElement(new Customer(1,"John","CA"));
    v.addElement(new Customer(2,"Aiden","NY"));
    v.addElement(new Customer(3,"Joe","PA"));
    Enumeration enum = v.elements();
    //now this enum is similar to the enumeration which your receive from EJBs

     try
     {
       dBTable1.refreshDataObject(enum, null);
     }
     catch(Exception e)
     {
       JOptionPane.showMessageDialog( this,"Error loading " + e.getMessage(),"",JOptionPane.OK_OPTION);
     }

  }

  class OrderModel extends CellPropertiesModel
  {
     public Color getForeground(int row, int col)
     {
          //if you want to have alternate rows colored differently
          //if(row % 2 == 0)
          //  return Color.white;
          //else
          // return Color.yellow;
          //similarly you can try coloring alternate cols

          //I want to highlight the cells whose product amounts are more
          //more than 3000.00
          if( col == 2)
          {
            Object cellValue = dBTable1.getTable().getValueAt(row, col);
            if( cellValue instanceof Double )
            {
              if(((Double)cellValue).doubleValue() > 3000.00 )
              {
                return Color.red;
              }
            }
            else
            {
              if( cellValue == null || "".equals(cellValue))
                return null;

              if(Double.valueOf((String)cellValue).doubleValue() > 3000.00 )
              {
                return Color.red;
              }
            }
          }


          //in all other cases let the cell have the default color
          return null;

     }

     public int getAlignment(int row, int col)
     {
        if( col== 0 || col == 6 || col ==7)
          return SwingConstants.LEFT;
        else if(col == 2)
          return SwingConstants.RIGHT;
        else
          return SwingConstants.CENTER;
     }
  }


    //whenever user changes a cell data, if you want to do some validation
    //add this listener
      class MyCellListener implements DBTableCellListener
      {
        public Object cellValueChanged(int row, int col, Object oldValue, Object newValue)
        {
          if( col == 3)
          {
            //the oldvalue and the new value will be a String type or the actual data type Double
            //In both cases find the double value and compare

              if( newValue instanceof Double )
              {
                if(((Double)newValue).doubleValue() > 5000.00 )
                {
                  JOptionPane.showMessageDialog( CustomerOrderDemo.this,"Product price cannot be more than $5000.00","",JOptionPane.OK_OPTION);

                  //newvalue is the user changed value, since the new value is greater than 5000
                  //we should return this oldvalue, so that the cell will still have the oldvalue
                  return oldValue;

                  //in the above you can also do
                  //return "5000.00";
                  //in that case even if the user enters more than 5000.00 still he will get 5000.00 in the cell
                  //the return value should always be string, but the data should be covertable to the correct format
                }
                else
                {
                  return newValue;
                }
              }
              else
              {
                if( newValue == null || "".equals(newValue))
                  return "";

                if(Double.valueOf((String)newValue).doubleValue() > 5000.00 )
                {
                  JOptionPane.showMessageDialog( CustomerOrderDemo.this,"Product price cannot be more than $5000.00","",JOptionPane.OK_OPTION);
                  return oldValue;
                }
                else
                {
                  return newValue;
                }
              }
          }
          //we don't care about other columns
          else
          {
            //in all other cases return new value so that the new value will be set in the cells
            return newValue;
          }
        }
      }


      //if we don't want quicktable to handle all the errors
      //and if we want to show meaning full error messages to user
      //then we have to listen for error and show correct error messages
      class MyErrorListener implements DBTableErrorListener
      {
        //this method will be called by quicktable, whenever an error occurs
        public boolean errorOccured(int errorId, String errorMessage, Exception unexpectedException)
        {

          //See DBTableErrorListener API help for errorId values
          if (errorId == DBTableErrorListener.DRIVER_NOT_FOUND)
          {
              JOptionPane.showMessageDialog( CustomerOrderDemo.this,"Installation Error: Add jdbc driver to classpath!","",JOptionPane.OK_OPTION);

              //you have handled the error, so return true
              //if you return false, quicktable will show the default message dialog
              return true;
          }
          else if (errorId == DBTableErrorListener.UPDATE_ERROR)
          {
              //the error code used here varies in different drivers
              //so change this based on your driver
              if(((SQLException)unexpectedException).getErrorCode() == 0 )
              {
                JOptionPane.showMessageDialog(CustomerOrderDemo.this,"Error: Your changes are not updated due to database error: " + unexpectedException.getMessage(),"",JOptionPane.OK_OPTION);

                //you have handled the error, so return true
                //if you return false, quicktable will show the default message dialog
                return true;
              }
              else
                return false;
          }
          //there are lot of other error cases , refer to DBTableErrorListener javadoc

          //all other errors need to be handled by dbtable, so return false
          return false;
        }
      }


      //Whenever a user tries to delete a record, we want to ask the user whether
      //he really wants to delete the record and once the record is delete, we
      //want to tell the user that this record is successfully deleted
      //to implement this we have to add a DatabaseChangeListener to quicktable

      class MyChangeListener extends DatabaseChangeListener
      {
          public boolean beforeDelete(int row)
          {
             //get the order number corresponding to this row
             Object orderNo = dBTable1.getTable().getValueAt(row, 0);

             int option = JOptionPane.showConfirmDialog( CustomerOrderDemo.this,"Are you sure to delete the Order:" + orderNo,"",JOptionPane.OK_CANCEL_OPTION);

             if( option == JOptionPane.OK_OPTION )
             {
               //if you want to delete, return true
               return true;
             }
             else
             {
               //if you want to cancel this delete, return false
               return false;
             }
          }

          public void afterDelete(int row)
          {
              JOptionPane.showMessageDialog( CustomerOrderDemo.this,"Sucessfully deleted","",JOptionPane.OK_OPTION);
          }


          public boolean onNewButtonClick()
          {
              //order No, is the primary key in this table, we don't want the user to create
              //a order number , we want to automatically create a order number , everytime
              //user inserts a new record
              Vector insertVector = new Vector();

              //this is just for example, don't follow this example of creating unique key because it may create duplicates
              insertVector.addElement(new Integer(Math.abs(randomOrderNumber.nextInt())));

              insertVector.addElement("");

              //Float & double doesn't work with simpletext , so used the default string
              //usually supply the correct datatype
              //insertVector.addElement( new Float(0.0));
              insertVector.addElement("");
              insertVector.addElement("");
              insertVector.addElement("");
              insertVector.addElement("");
              insertVector.addElement("");
              insertVector.addElement("");
              insertVector.addElement("");
              insertVector.addElement("");
              insertVector.addElement("");

              try{
              dBTable1.insert(insertVector);
              }
              catch(Exception e)
              {
                 JOptionPane.showMessageDialog( CustomerOrderDemo.this,e.getMessage(),"Error",JOptionPane.OK_OPTION);
              }

              //since we have already inserted the record, return true, so that
              //quicktable doesn't insert the default record
              return false;
          }

          //there are more methods in this class beforeUpdate, afterUpdate, beforeInsert, afterInsert, onDeleteButtonClick
          //you can use them too.
      }


    //lets say, one of the column stores dates in the database, unfortunately, the data type of
    //this column was varchar, so it is stored as text in database. Still we want to use this
    //column like a Date type column in quicktable, so that the users can use the calendar bean to
    //to select a date instead of typing directly. This DataMap class handles the conversion between
    // Date to string & vice versa
    public class DateStringMap implements DataMap
    {
      java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("MM/dd/yyyy");

      //this method will be called whenever we try to display this data
      public Object convertDataToDisplay(Object val)
      {
        //warning: please make sure, you don't put a time consuming code here, make it very simple
        //otherwise this will bring down the performance of quicktable

          if( val instanceof java.util.Date)
          {
            //the data is already in date object, so no need to convert
            return val;
          }
          else
          {
            try
            {
              //convert the String to a Date
              return df.parse((String)val);
            }
            catch(Exception e)
            {
              //if the data is not in correct format, return today's date
              return new java.util.Date();
            }
          }
      }

      //this method will be called whenever we try to save this data to database
      public Object convertDataToStore(Object val)
      {
        if( val instanceof java.util.Date)
        {
          try
          {
            return df.format((java.util.Date)val);
          }
          catch(Exception e)
          {
            //this case will never happen , if you use quicktable's default calender editor
            return null;
          }
        }
        else
        {
          //this case will also not happen, if you use quicktable's default calender editor
          return null;
        }

      }
    }


  //we create a File selecter cell editor
  //this has a label & a button, when user wants to change the file to something else
  //instead of directly editing this cell, they click on the button which opens a file
  // dialog and user selects the file
  class FileCell extends JPanel implements CellComponent
  {
      JLabel jl = new JLabel();
      JButton jb = new JButton("...");
      JFileChooser jf;

      public FileCell()
      {
        //use a border layout , rather than the used flow layout
        add(jl);
        add(jb);

        // add a actionlistener to open file dialog when user clicks on the button
        jb.addActionListener(new ActionListener()
        {
          public void actionPerformed(ActionEvent e)
          {
              if( jf == null)
              {
                jf = new JFileChooser();
              }

              String val = jl.getText();

              if(  val != null   &&   !("".equals(val)) )
              {
                jf.setCurrentDirectory(new File(val));
              }

              int returnVal = jf.showOpenDialog(null);

              if(returnVal == JFileChooser.APPROVE_OPTION)
                jl.setText(jf.getSelectedFile().getPath());
          }
        });
      }

      public void setValue(Object value)
      {
        jl.setText( (String)(value==null?"":value ));
      }

      public Object getValue()
      {
        String val = jl.getText();

        if(  val != null   &&   !("".equals(val))  )
          return val;
        else
          return null;
      }


      public JComponent getComponent()
      {
         return this;
      }

  }


  class OrderPrintProperties extends PrintProperties
  {
     String header = "                                      Customer Order Summary Report\nPage: %1%\nSub Page: %2%\nDate: ";

     public String getHeader()
     {
        return header + new java.util.Date() + "\n ";
     }

     public String getFooter()
     {
        return "Confidential";
     }

     public int getHeaderAlign()
     {
        return SwingUtilities.LEFT;
     }

     public Color getHeaderColor()
     {
        return Color.red;
     }
  }

  //This filter is just to show an example of how to implement a filter
  //this filters all the records whose first column's data is a number and is a odd number
   public class OddFilter implements Filter
   {
        public int[] filter(javax.swing.table.TableModel tm)
        {
          Vector v = new Vector();

          //finds all the records whose first column's data is a odd number
          for( int i=0; i< tm.getRowCount(); i++)
          {
             //get the first column's data
             Object data = tm.getValueAt(i,1);

             if( data == null)
              continue;

              try
              {
                int val = -1;

                //get the integer value of the data
                if( data instanceof Integer)
                  val = ((Integer)data).intValue();
                else
                  val = Integer.parseInt(data.toString());

                //check whether the data is odd
                //if the data is odd, add that row to the vector
                if( (val % 2) != 0 )
                  v.addElement(new Integer(i));
              }
              catch(Exception e){}
          }

          //now we have the filtered rows in the vector
          //create a int array from thet vector
          int arr[] = new int[v.size()];

          for(int i=0; i< v.size(); i++)
          {
            arr[i] = ((Integer)v.elementAt(i)).intValue();
          }

          return arr;
        }
  }

  private void createToolBar()
  {

    //create Toolbar
    JToolBar jb = new JToolBar();
    Insets i1 = new Insets(0, 0, 0, 0);
    printButton = new JButton(new ImageIcon(this.getClass().getResource("/images/print.gif")));
    printButton.setToolTipText("Print");
    printButton.setMargin(i1);
    printButton.setAlignmentY(Component.CENTER_ALIGNMENT);
    printButton.addActionListener(this);
    jb.add(printButton);

    previewButton = new JButton(new ImageIcon(this.getClass().getResource("/images/print.gif")));
    previewButton.setToolTipText("Print Preview");
    previewButton.setMargin(i1);
    previewButton.setAlignmentY(Component.CENTER_ALIGNMENT);
    previewButton.addActionListener(this);
    jb.add(previewButton);

    findButton = new JButton(new ImageIcon(this.getClass().getResource("/images/find.gif")));
    findButton.setToolTipText("Find");
    findButton.setMargin(i1);
    findButton.setAlignmentY(Component.CENTER_ALIGNMENT);
    findButton.addActionListener(this);
    jb.add(findButton);

    replaceButton = new JButton(new ImageIcon(this.getClass().getResource("/images/replace.gif")));
    replaceButton.setToolTipText("Replace");
    replaceButton.setMargin(i1);
    replaceButton.setAlignmentY(Component.CENTER_ALIGNMENT);
    replaceButton.addActionListener(this);
    jb.add(replaceButton);

    jb.addSeparator();
    jb.addSeparator();

    JLabel jl = new JLabel("Show");
    jl.setAlignmentY(Component.CENTER_ALIGNMENT);
    jb.add(jl);

    selectionCombo = new JComboBox();
    selectionCombo.setMaximumSize(new Dimension(70,20));
    selectionCombo.setAlignmentY(Component.CENTER_ALIGNMENT);
    selectionCombo.addItem("Order");
    selectionCombo.addItem("Product");
    selectionCombo.addItem("Customer");
    selectionCombo.addActionListener(this);
    jb.add(selectionCombo);

    refreshButton = new JButton(new ImageIcon(this.getClass().getResource("/images/refresh.gif")));
    refreshButton.setToolTipText("Refresh");
    refreshButton.setMargin(i1);
    refreshButton.setAlignmentY(Component.CENTER_ALIGNMENT);
    refreshButton.addActionListener(this);
    jb.add(refreshButton);

    jb.addSeparator();
    jb.addSeparator();

    JLabel j2 = new JLabel("Skin");
    j2.setAlignmentY(Component.CENTER_ALIGNMENT);
    jb.add(j2);

    skinCombo = new JComboBox();
    skinCombo.setMaximumSize(new Dimension(70,20));
    skinCombo.setAlignmentY(Component.CENTER_ALIGNMENT);
    skinCombo.addItem("None");
    skinCombo.addItem("Simple");
    skinCombo.addItem("Cool");
    skinCombo.addItem("Pulse");
    skinCombo.addActionListener(this);
    jb.add(skinCombo);

    jb.addSeparator();
    jb.addSeparator();

    filterLabel = new JLabel("Find order");
    filterLabel.setAlignmentY(Component.CENTER_ALIGNMENT);
    jb.add(filterLabel);

    filterText = new JTextField();
    filterText.setColumns(10);
    filterText.setAlignmentY(Component.CENTER_ALIGNMENT);
    jb.add(filterText);

    filterButton = new JButton("Go");
    filterButton.setMargin(i1);
    filterButton.setAlignmentY(Component.CENTER_ALIGNMENT);
    filterButton.addActionListener(this);
    jb.add(filterButton);

    jb.addSeparator();
    jb.addSeparator();

    filterCheckbox = new JCheckBox("Odd Records Only");
    filterCheckbox.addActionListener(this);
    jb.add(filterCheckbox);

    getContentPane().add(jb,BorderLayout.NORTH);

  }

  public static void main(String[] args)
  {
    try{ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());}catch(Exception e){}

    //create a new table frame
    CustomerOrderDemo myframe = new CustomerOrderDemo();
    System.out.println("Warning: SimpleText driver fails to update using a prepared statement. It throws a \"Invalid data format\" error.");
    System.out.println("This error is not due to quicktable. But due to the jdbc driver. when you use a standard jdbc driver you won't get these errors");
    System.out.println("Configure odbc datasource \"quicktabledemo\" using the quicktable.mdb file in database directory and try the samples under samples/MSAccessSample");

    JOptionPane.showMessageDialog(myframe,"Modifying cell data, may fail due to simple text jdbc driver problem!");
  }
}

 


botcurve.gif (60 bytes)
botblack.gif (108 bytes)