Home > Articles > Programming > Java

Like this article? We recommend

Like this article? We recommend

Creating Your Own Renderers

One of the most interesting features offered by table components is a table component's ability to customize cell renderering on a column by column basis. Essentially, you attach a custom renderer to a column, and the renderer takes charge of painting that column's cells. For example, you can attach to a favorite color column a renderer that draws images, and that renderer will display those images in the favorite color column's cells. What would the resulting table component look like? Look at Figure 10.

Figure 10 Because a table component supports custom column rendering, you can render images of employee favorite colors in a favorite color column.

The TableDemo10 program that generated Figure 10 was not hard to write. To see what its source code looks like, examine Listing 10.

Listing 10: TableDemo10.java

// TableDemo10.java

import java.awt.*;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;

class TableDemo10 extends JFrame
{
  TableDemo10 (String title)
  {
   // Pass the title to the JFrame superclass so that it appears in
   // the title bar.

   super (title);

   // Tell the program to exit when the user either selects Close
   // from the System menu or presses an appropriate X button on the
   // title bar.

   setDefaultCloseOperation (EXIT_ON_CLOSE);

   // Create a my table model consisting of 4 rows by 3 columns.

   MyTableModel mtm = new MyTableModel (4, 3);

   // Assign column identifiers (headers) to the columns.

   String [] columnTitles =
   {
     "Name",
     "Address",
     "Fav. Color",
   };

   mtm.setColumnIdentifiers (columnTitles);

   // Populate all cells in the my table model.

   String [] names =
   {
     "John Doe",
     "Jane Smith",
     "Jack Jones",
     "Paul Finch"
   };

   String [] addresses =
   {
     "200 Fox Street",
     "Apt. 555",
     "Box 9000",
     "1888 Apple Avenue"
   };

   ImageIcon iiRed = new ImageIcon ("red.gif");

   Icon [] favColors =
   {
     iiRed,
     new ImageIcon ("green.gif"),
     new ImageIcon ("blue.gif"),
     iiRed
   };

   int nrows = mtm.getRowCount ();

   for (int i = 0; i < nrows; i++)
   {
      mtm.setValueAt (names [i], i, 0);
      mtm.setValueAt (addresses [i], i, 1);
      mtm.setValueAt (favColors [i], i, 2);
   }

   // Create a table using the previously created my table
   // model.

   JTable jt = new JTable (mtm);

   // Increase the height of each row by 50% so we can see the whole
   // image.

   jt.setRowHeight (3 * jt.getRowHeight () / 2);

   // Place the table in a JScrollPane object (to allow the table to
   // be vertically scrolled and display scrollbars, as necessary).

   JScrollPane jsp = new JScrollPane (jt);

   // Add the JScrollPane object to the frame window's content pane.
   // That allows the table to be displayed within a displayed scroll
   // pane.

   getContentPane ().add (jsp);

   // Establish the overall size of the frame window to 400
   // horizontal pixels by 175 vertical pixels.

   setSize (400, 175);

   // Display the frame window and all contained
   // components/containers.

   setVisible (true);
  }

  public static void main (String [] args)
  {
   // Create a TableDemo10 object, which creates the GUI.

   new TableDemo10 ("Table Demo #10");
  }
}

class MyTableModel extends DefaultTableModel
{
  MyTableModel (int rows, int cols)
  {
   super (rows, cols);
  }

  public Class getColumnClass (int columnIndex)
  {
   // If column is the Fav. Color column, return Icon.class so
   // that the Icon renderer will be used.

   if (columnIndex == 2)
     return Icon.class;
   else
     return Object.class;
  }
}

When a JTable object is created, several default renderers are also created. Those renderers are capable of rendering Boolean choices, dates, image icons, numbers, and objects (as strings). If you do not explicitly attach a custom render to a column, a table component chooses a default renderer on your behalf. By default, that renderer renders objects as strings (for all columns). To change to different default renderers, you must override the getColumnClass(int columnIndex) method in your model. That is exactly what TableDemo10 does: It overrides that method in a MyTableModel class.

If you examine MyTableModel's getColumnClass(int columnIndex) method, you will see that it returns the Icon.class Class object when columnIndex equals 2 (the third column). Otherwise, Object.class returns. Returning Icon.class (or ImageIcon.class) for the third column is all that is required to establish an image renderer for that column.

Before image rendering can occur, some images are required. Take a look at TableDemo10's constructor, and you will encounter the following code fragment:

ImageIcon iiRed = new ImageIcon ("red.gif");

Icon [] favColors =
{
  iiRed,
  new ImageIcon ("green.gif"),
  new ImageIcon ("blue.gif"),
  iiRed
};

The code fragment creates an array of Icon references to ImageIcon objects, and each ImageIcon object loads a GIF file. Notice that the ImageIcon object reference in iiRed is assigned to entries 0 and 3 in the favColors array. If the same image is going to appear in multiple cells, why load that image multiple times and waste memory storing duplicates? That is why I have chosen to reference the same object from two array entries.

In addition to the above code fragment, mtm.setValueAt (favColors [i], i, 2); is called (in a loop) to assign favColors's Icon references to the third column's cell values in the table component's model. Nothing else needs to be done (except, perhaps, to adjust the height of the rows—by calling JTable's setRowHeight(int rowHeight) method—so the entire image can be displayed). Images now appear in the third column's cells (assuming that the GIF files can be found in the current directory, and no problems occur during ImageIcon's internal file loading activity).

To use other default renderers, you need to know what Class objects to return from getColumnClass(int columnIndex). Table 8 itemizes all default renderers and their associated Class objects.

Table 8 Class Objects and Default Renderers

Class Object

Default Renderer

Boolean.class

Renders a check box with a check mark (to represent true) or no check mark (to represent false).

Date.class

Renders a date using a date formatter. (See the DateFormat class and its getDateInstance() and format (Object value) methods for more information.)

Double.class

Renders a floating-point value using a numeric formatter. The value is aligned with the right edge of a cell's border. (See the NumberFormat class and its getInstance() and format(Object value) methods for more information.)

Float.class

A synonym for Double.class. Same renderer is used.

Icon.class

Renders a centered image using an image renderer.

ImageIcon.class

A synonym for Icon.class. Same renderer is used.

Number.class

Renders any kind of integer or floating-point number in a right-aligned format.

Object.class

Converts the contents of any object to a String (by calling the object's toString() method) and renders the String's characters in a left-aligned format.


The Number.class renderer is interesting in that both integer and floating-point values can be rendered. As a result, you could construct the following array of Number references to objects that are passed to a model (by way of setValueAt(Object v, int rowIndex, int columnIndex), and the numeric renderer would render each number appropriately:

Number [] numbers =
{
  new BigInteger ("8888888888888888888888888888888888888888888"),
  new BigDecimal ("1e+500"),
  new Byte ((byte) 10),
  new Double (3.15),
  new Float (1.5),
  new Integer (20),
  new Long (3000000000L),
  new Short ((short) 30000)
};

Renderers in Depth

Eventually, you will discover that a table component's default renderers do not meet your needs. At that time, you will want to develop a custom renderer. You accomplish that task by doing two things. First, you create a class that implements the TableCellRenderer interface and overrides that interface's getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) method to return a Component reference to an object that performs the actual rendering. Second, you create an object from your class and call TableColumn's setCellRenderer(TableCellRenderer tcr) method to establish that object as a renderer for one or more columns. Alternatively, you can call TableColumn's setHeaderRenderer(TableCellRenderer tcr) method to establish that object as a renderer for one or more column header cells.

Creating a custom renderer is not as difficult as it sounds. For your first taste of a custom renderer, examine the TableDemo11 source code in Listing 11.

Listing 11: TableDemo11.java

// TableDemo11.java

import java.awt.*;

import javax.swing.*;
import javax.swing.table.*;

class TableDemo11 extends JFrame
{
  TableDemo11 (String title)
  {
   // Pass the title to the JFrame superclass so that it appears in
   // the title bar.

   super (title);

   // Tell the program to exit when the user either selects Close
   // from the System menu or presses an appropriate X button on the
   // title bar.

   setDefaultCloseOperation (EXIT_ON_CLOSE);

   // Create a default table model consisting of 4 rows by 3 
   // columns.

   DefaultTableModel dtm = new DefaultTableModel (4, 3);

   // Assign column identifiers (headers) to the columns.

   String [] columnTitles =
   {
     "Name",
     "Address",
     "Favorite Color",
   };

   dtm.setColumnIdentifiers (columnTitles);

   // Populate all cells in the default table model.

   String [] names =
   {
     "John Doe",
     "Jane Smith",
     "Jack Jones",
     "Paul Finch"
   };

   String [] addresses =
   {
     "200 Fox Street",
     "Apt. 555",
     "Box 9000",
     "1888 Apple Avenue"
   };

   String [] favoriteColors =
   {
     "red",
     "blue",
     "green",
     "yellow"
   };

   int nrows = dtm.getRowCount ();

   for (int i = 0; i < nrows; i++)
   {
      dtm.setValueAt (names [i], i, 0);
      dtm.setValueAt (addresses [i], i, 1);
      dtm.setValueAt (favoriteColors [i], i, 2);
   }

   // Create a table using the previously created default table
   // model.

   JTable jt = new JTable (dtm);

   // Establish a color renderer for the third column.

   jt.getColumnModel ().getColumn (2).
              setCellRenderer (new ColorRenderer());

   // Place the table in a JScrollPane object (to allow the table to
   // be vertically scrolled and display scrollbars, as necessary).

   JScrollPane jsp = new JScrollPane (jt);

   // Add the JScrollPane object to the frame window's content pane.
   // That allows the table to be displayed within a displayed scroll
   // pane.

   getContentPane ().add (jsp);

   // Establish the overall size of the frame window to 400
   // horizontal pixels by 110 vertical pixels.

   setSize (400, 110);

   // Display the frame window and all contained
   // components/containers.

   setVisible (true);
  }

  public static void main (String [] args)
  {
   // Create a TableDemo11 object, which creates the GUI.

   new TableDemo11 ("Table Demo #11");
  }
}

class ColorRenderer extends JLabel implements TableCellRenderer
{
  ColorRenderer ()
  {
   // Ensure that all nonforeground pixels are painted in the
   // background.
   // color.

   setOpaque (true);

   // Switch off JLabel's use of BOLD.

   setFont (getFont ().deriveFont (Font.PLAIN));
  }

  public Component getTableCellRendererComponent (JTable table,
                          Object value,
                          boolean isSelected,
                          boolean isFocus,
                          int row,
                          int column)
  {
   // As a safety check, it's always good to verify the type of
   // value.

   if (value instanceof String)
   {
     String s = (String) value;

     // Establish an appropriate background color. That color
     // remains in effect for all columns to which the
     // ColorRenderer object
     // is attached until setBackground(Color c) is called again.

     if (s.equals ("red"))
       setBackground (Color.red);
     else
     if (s.equals ("green"))
       setBackground (Color.green);
     else
     if (s.equals ("blue"))
       setBackground (Color.blue);
     else
     if (s.equals ("yellow"))
       setBackground (Color.yellow);
     else
       setBackground (Color.white);

     // Ensure text is displayed horizontally.

     setHorizontalAlignment (CENTER);

     // Assign the text to the JLabel component.

     setText (s);
   }

   // Return a reference to the ColorRenderer (JLabel subclass)
   // component. Behind the scenes, that component will be used to
   // paint the pixels.

   return this;
  }
}

TableDemo11 accomplishes the same task as TableDemo10, in that it displays a favorite color in a table component's third column. However, instead of displaying an image of a color in a cell, TableDemo11 establishes a renderer that colors every pixel in that cell and prints the color's name as well, as shown in Figure 11.

Figure 11 A custom renderer displays text over a colored background.

TableDemo11 executes the following method call on JTable reference jt, to assign a custom ColorRenderer renderer object to the table component's third column: jt.getColumnModel ().getColumn (2).setCellRenderer (new ColorRenderer());. The ColorRenderer() constructor ensures that a background color is used to paint all background pixels in a cell by calling JComponent's setOpaque(boolean isOpaque) method. Then ColorRenderer() changes a JLabel's default font style from bold to plain because cell text looks better when it isn't bold (in my opinion).

At some point, the getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) method will be called to return a Component reference to an object that is capable of painting a cell's pixels. Of course, a JTable object reference is passed to that method to facilitate calling JTable methods. The object referenced by value contains the object to appear in the cell. That value doesn't have to be a String. It can be whatever has been assigned to the appropriate column of cell values in the table component's model. The isSelected and hasFocus flags determine whether a cell should be rendered as a selected cell or a focused cell. The cell is rendered as a selected cell if isSelected is true and hasFocus is false. If hasFocus is true, the cell is rendered as a focused cell. Finally, row and column identify the table cell to be rendered. If you attach the same custom renderer to multiple columns, you can use column to distinguish one column from another, in case you want to customize your rendering on a per-column basis. Whether you attach a custom renderer to one or more columns, you can use row to distinguish one row from another, to customize the rendering of different rows.

Inside getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column), you will probably want to validate the type of value to prevent cast problems later. Although it's not really necessary in the TableDemo11 program because the type of all cells assigned to the third column in the table component's model is String and because the custom renderer is assigned to only that column, it is still a good idea to perform that validation (because you might later change the type of the column's values or attach the same custom renderer to multiple columns of different types). In TableDemo11, if value is of the appropriate type, a call is made to a setBackground(Color c) method to choose an appropriate background color. Notice that equals(Object o) is called to compare value's contents (once cast to a String) against "red", "green", "blue", and "yellow", and an appropriate setBackground(Color c) method call occurs if there is a match. If there is no match (because value contains an invalid string of characters, such as redx instead of red), the background color is set to white. After the background color is set, JLabel's setText(String s) method is called to save the String contents (for future rendering), and a reference to the ColorRenderer object returns. That renderer will be used to call the paint(Graphics g, JComponent c) method in JLabel's UI delegate.

TIP

Instead of subclassing JLabel and implementing TableCellRenderer, Sun recommends that you subclass DefaultTableCellRenderer (which already subclasses JLabel and implements TableCellRenderer) whenever you need to use a JLabel as a renderer. Sun recommends doing that because there are performance advantages. To find out what those advantages are, review the SDK documentation for DefaultTableCellRenderer.

How Rendering Works

When a table component's cells must be rendered, the Abstract Windowing Toolkit (AWT) painting system calls JComponent's paint(Graphics g) method. Among its various tasks, paint(Graphics g) calls JComponent's paintComponent(Graphics g) method. In turn, that method calls the UI delegate's update(Graphics g, JComponent c) method. That method results in a call to the UI delegate's paint(Graphics g, JComponent c) method, which (for a table component's UI delegate) calls a paintGrid(Graphics g, int rMin, int rMax, int cMin, int cMax) method (to render a table component's grid) followed by a paintCells(Graphics g, int rMin, int rMax, int cMin, int cMax) method (to render the cells). That latter method calls the UI delegate's paintCell(Graphics g, Rectangle cellRect, int row, int column)—and that is where the rendering (for a specific cell) takes place.

When paintCell(Graphics g, Rectangle cellRect, int row, int column) is called, g identifies the graphics context (whose methods will perform the actual rendering), cellRect identifies the location and dimensions of the rectangle in which rendering will occur, row identifies the cell row, and column identifies the cell column. Having the cell's row and column is necessary so that its value can be extracted from the model. The following code fragment (taken from BasicTableUI) presents the source code to paintCell(Graphics g, Rectangle cellRect, int row, int column):

private void paintCell (Graphics g, Rectangle cellRect, int row, 
            int column)
{
  // Painting occurs anytime a component sustains damage. For the 
  // table component, it might be in the process of editing a cell's
  // contents when a paint request occurs. If the table component is
  // editing, and if the cell about to be painted is the cell being 
  // edited, have the editor component move and resize itself to the 
  // appropriate cell area of the table component's visual 
  // representation (which will probably result in a repaint of the 
  // editor component) by calling setBounds(), and mark the editor as
  // valid (so a layout manager will not attempt to perform a layout
  // operation involving the editor component).

  if (table.isEditing () && table.getEditingRow () == row && 
    table.getEditingColumn () == column)
  {
    Component component = table.getEditorComponent ();
    component.setBounds (cellRect);
    component.validate ();
  }
  else
  {
    // To render a cell, the first thing that is needed is a
    // renderer. The following method call obtains the renderer 
    // associated with the cell at (row, column).

    TableCellRenderer renderer = table.getCellRenderer (row, 
                              column);

    // Once a renderer has been obtained, it must be prepared for
    // use in rendering. The following method call allows the 
    // renderer to select a Component object and configure that
    // object (by setting the Component's foreground and background
    // colors, font, and anything else that is appropriate). The 
    // Component object that returns will be used to perform the 
    // rendering.

    Component component = table.prepareRenderer (rendererer, row, 
                          column);

    // The following renderingPane variable references a 
    // CellRendererPane object. That object's 
    // paintComponent(Graphics g, Component c, int x, int y, int 
    // width, int height, boolean shouldValidate) method is called
    // to configure the component's location so that the component 
    // is drawn in the right location, mark the component as valid
    // so a layout manager will not attempt to perform a layout 
    // operation involving the component, and invoke the 
    // component's paint(Graphics g) method to paint the actual 
    // pixels.

    rendererPane.paintComponent (g, component, table, cellRect.x, 
                  cellRect.y, cellRect.width, 
                  cellRect.height, true);
  }
}

How does getCellRenderer(int rowIndex, int columnIndex) extract a renderer? The following source code (taken from the JTable class) demonstrates this:

public TableCellRenderer getCellRenderer (int row, int column)
{
  // Acquire a reference to the TableColumn object associated with
  // column.

  TableColumn tableColumn = getColumnModel ().getColumn (column);

  // Fetch the renderer associated with the TableColumn object.

  TableCellRenderer renderer = tableColumn.getCellRenderer ();

  // If the developer has not specified a renderer for that column,
  // obtain a reference to the default renderer.

  if (renderer == null)
    renderer = getDefaultRenderer (getColumnClass (column));

  return renderer;
}

When a JTable object is created, a group of default renderers is installed. Those renderers are capable of rendering objects as strings and rendering numbers, dates, Booleans, and icons. If a developer does not explicitly specify a renderer for a column (by calling TableColumn's setCellRenderer(TableCellRenderer r) method), JTable's getCellRenderer(int rowIndex, int columnIndex) method calls getColumnClass (column) to return a Class object that identifies the type of a column. Using that value, JTable's getDefaultRenderer(Class c) method is called to return a renderer associated with the Class object referenced by c.

Following the call to getCellRenderer(int rowIndex, int columnIndex), paintCell(Graphics g, Rectangle cellRect, int row, int column) calls JTable's prepareRenderer(TableCellRenderer renderer, int row, int column) method to set up the renderer in preparation for rendering, as the following source code demonstrates:

public Component prepareRenderer (TableCellRenderer renderer, int row, 
                 int column)
{
  // Contact the model (via JTable's convenience method) to retrieve 
  // the value of the cell at (row, column).

  Object value = getValueAt (row, column);

  // Contact the selection model (via JTable's convenience method) to 
  // determine if the cell about to be rendered is a selected cell. If
  // so, it should be rendered with some kind of selection indicator
  // (such as the light bluish-purple background that appears under
  // the Java look and feel, if the cell's type is Object.class). 

  boolean isSelected = isCellSelected (row, column);

  // Contact the selection model to determine if the cell is selected 
  // but if it represents an anchor cell – the first cell of a
  // selection interval. In that case, the cell must be specially
  // rendered (such as having a thicker light bluish-purple border and
  // a white background under the Java look and feel, if the cell's 
  // type is Object.class).

  boolean rowIsAnchor = (selectionModel.getAnchorSelectionIndex () 
             == row);
  boolean colIsAnchor = (columnModel.getSelectionModel ().
             getAnchorSelectionIndex () == column);

  // If the cell is an anchor selection cell, and if it has the focus,
  // that cell must be set apart from other selected cells (such as
  // having a thicker black border and a white background under the
  // Java look and feel, if the cell's type is Object.class).

  boolean hasFocus = (rowIsAnchor && colIsAnchor) && isFocusOwner ();

  // The previously determined values are passed to the following
  // method. Those values determine how the cell value appears, as
  // well as selection and focus.

  return renderer.getTableCellRendererComponent (this, value,
                         isSelected, hasFocus,
                         row, column);
} 

Once preparation is complete, a Component object returns from prepareRenderer(TableCellRenderer renderer, int row, int column). That object is used to perform the actual painting. The beginning of the painting process starts with rendererPane.paintComponent (g, component, table, cellRect.x, cellRect.y, cellRect.width, cellRect.height, true);. That method call results in the Component's paint(Graphics g) method being called. Assuming the Component reference is actually a JComponent subclass reference (such as a JLabel reference), the paint(Graphics g, JComponent c) method of the component's UI delegate eventually gets called to do the actual painting.

The process by which a table component renders cells is intricate and can come across as being confusing. However, without that process, you would not be able to create custom renderers that paint cells any way you want. Hopefully, you now have a taste for rendering and will be able to create your own custom renderers.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020