|
|
By default, when the user drags the divider, the components in the split pane are not redrawn until the drag operation is complete. However, the setContinuousLayout method can be passed the parameter of true to force the components to be laid out and painted as the user drags the divider. The current value of this property can be queried with the isContinuousLayout method. Be careful about setting the CONTINUOUS_LAYOUT_ PROPERTY to true. For complex components in the split pane, the dragging can become very slow, making your application appear sluggish to the user.
The JSplitPaneTest application is a complete example of the JSplitPane class. It is shown in Listing 16.1. A static main method is provided to execute the application. In the main method, an ApplicationFrame instance is instantiated. Then an instance of the JSplitPaneTest class is constructed and added to the content pane of the frame. Finally, the frame is displayed. In the JSplitPaneTest class constructor, a JSplitPane instance is created and a table and tabbed pane are added to the right and left sides, respectively. The table and tabbed pane classes were presented in Chapters 11 and 12, and the details of their usage wont be repeated here. The frame containing the split pane created by the JSplitPaneTest application is shown in Figure 16.2.
Listing 16.1 The JSplitPaneTest Application
package com.foley.test;
import java.awt.*;
import java.awt.event.*;
import java.io.Serializable;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.table.*;
import com.foley.utility.JBox;
import com.foley.utility.ApplicationFrame;
/**
* An application that displays a JSplitPane in a frame.
* The components in the split pane are a table and
* a tabbed pane.
* <p>
* @author Mike Foley
**/
public class JSplitPaneTest extends Object {
/**
* The splitPane for the test.
**/
JSplitPane splitPane;
/**
* JSplitPaneTest, Constructor
* <p>
* Create a splitpane and add a table and tabbedpane
* to the splitpane.
**/
public JSplitPaneTest() {
splitPane = new JSplitPane();
splitPane.setRightComponent( createTabbedPane() );
splitPane.setLeftComponent( createTable() );
}
/**
* @return The split pane.
**/
public JSplitPane getSplitPane() {
return( splitPane );
}
/**
* Create the tabbed pane used in the application.
* Add a few interesting tabs.
* <p>
* @return The tab pane instance for this application.
**/
protected JTabbedPane createTabbedPane() {
JTabbedPane tabbedPane = new JTabbedPane();
addTab( tabbedPane, "Tab1" );
addTab( tabbedPane, "Tab2" );
addTab( tabbedPane, "Tab3" );
tabbedPane.setForegroundAt( 0, Color.red );
tabbedPane.setBackgroundAt( 0, Color.yellow );
tabbedPane.setForegroundAt( 1, Color.yellow );
tabbedPane.setBackgroundAt( 1, Color.red );
return( tabbedPane );
}
/**
* Create a table and place the table in a scrollpane.
* <p>
* @return The scrollpane containing the table.
**/
public JComponent createTable() {
JTable table = new JTable( new TableTestModel() );
//
// Create and register a Color class renderer.
//
DefaultTableCellRenderer colorRenderer =
new DefaultTableCellRenderer() {
public void setValue( Object value ) {
setBackground( ( Color )value );
}
};
colorRenderer.setOpaque( true );
table.setDefaultRenderer( Color.class, colorRenderer );
table.setDefaultRenderer( Boolean.class,
new SelectedCheckBoxRenderer() );
JScrollPane scrollPane = new JScrollPane( table );
return( scrollPane );
}
/**
* Create a JLabel and add it to the tabbed pane.
* The text of the label matches the tabs text, and
* is simply the number of tabs created during this
* run of the application.
**/
private void addTab( final JTabbedPane tabbedPane, String name ) {
final JPanel panel = new JPanel();
panel.setLayout( new BorderLayout() );
panel.add( new JLabel( name ), BorderLayout.NORTH );
final JTextField textField = new JTextField( name );
JBox box = JBox.createHorizontalJBox();
box.add( new JLabel( "Tab name: " ) );
textField.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent event ) {
//
// Update the title of our tab to that entered.
//
String newTitle = textField.getText();
int index = tabbedPane.indexOfComponent( panel );
tabbedPane.setTitleAt( index, newTitle );
//
// validate and paint the tabs to display properly.
//
tabbedPane.revalidate();
tabbedPane.repaint();
}
} );
box.add( textField );
panel.add( box, BorderLayout.SOUTH );
tabbedPane.add( panel, name );
tabbedPane.revalidate();
}
/**
* Application entry point.
* Create the frame, and display a splitpane in it.
*
* @param args Command line parameter. Not used.
**/
public static void main( String args[] ) {
JFrame frame = new ApplicationFrame( "JSplitPaneTest" );
JSplitPaneTest test = new JSplitPaneTest();
frame.getContentPane().add( test.getSplitPane(),
BorderLayout.CENTER );
frame.pack();
frame.setVisible( true );
} // main
} // JSplitPaneTest
/**
* Table model that returns the Class of the data in
* a particular column. This allows the table to set
* renderers for the data.
**/
class TableTestModel extends AbstractTableModel
implements Serializable {
/**
* The data in the model.
**/
Object[][] data = {
{ "Mike", Color.blue, new Boolean( true ), new Integer( 9 ) },
{ "Mari", Color.red, new Boolean( true ), new Integer( 6 ) },
{ "Molly", Color.yellow, new Boolean( false ), new Integer( 1 ) },
{ "Betsy", Color.orange, new Boolean( false ), new Integer( 8 ) },
{ "Bobby", Color.lightGray, new Boolean( true ), new Integer( 7 ) },
{ "Trisha", Color.gray, new Boolean( false ), new Integer( 10 ) },
{ "Sam", Color.white, new Boolean( true ), new Integer( 12 ) },
{ "John", Color.black, new Boolean( false ), new Integer( 11 ) } };
/**
* The column names for the model.
**/
String[] columnNames = { "Name", "Color", "Enabled", "Size" };
/**
* TableTestModel, constructor.
**/
TableTestModel() {
super();
}
/**
* getRowCount, from TableModel.
*
* @return The number of rows in the data.
**/
public int getRowCount() {
return( data.length );
}
/**
* getColumnCount, from TableModel.
*
* @return The number of columns in the data.
**/
public int getColumnCount() {
return( data[0].length );
}
/**
* getValueAt, from TableModel.
*
* @param row The row of the reqeusted data object.
* @param column The column of the reqeusted data object.
* @return The object at the specified cell.
**/
public Object getValueAt( int row, int column ) {
return( data[ row ][ column ] );
}
/**
* setValueAt, from TableModel.
*
* Set the data value in the given location to the
* given object.
*
* @param value The new data object.
* @param row The row of the new data object.
* @param column The column of the new data object.
**/
public void setValueAt( Object value, int row, int column ) {
if( column == 0 )
throw new RuntimeException(
"The Name column is not editable" );
data[ row ][ column ] = value;
fireTableCellUpdated( row, column );
}
/**
* getColumnName, from TableModel.
*
* @param column The column index whose name is desired.
* @return The name of the column with the given index.
**/
public String getColumnName( int column ) {
return( columnNames[ column ] );
}
/**
* getColumnClass, from TableModel.
*
* @param column The column index whose Class is desired.
* @return The Class of the data for the column with the given index.
**/
public Class getColumnClass( int column ) {
return( data[0][ column ].getClass() );
}
/**
* isCellEditable, from TableModel.
*
* All columns except the first are editable in this model.
*
* @param row The row of the cell whose editablility is requested.
* @param column The column of the cell whose state is requested.
* @return true if the cell is editable, false otherwise.
**/
public boolean isCellEditable( int row, int column ) {
if( column == 0 ) {
return( false );
} else {
return( true );
}
}
}
/**
* ColorCellRenderer is a rendering class that expects
* Color values. When this is the case, it paints the color
* as the background of the label. If not, show the String
* returned from the toString method of the value Object.
*
* @author Mike Foley
**/
class ColorCellRenderer extends JLabel
implements ListCellRenderer, Serializable {
Border selectedWhiteBorder;
Border selectedBlackBorder;
/**
* ColorCellRenderer, default constructor.
* We must be opaque so the background is painted.
**/
public ColorCellRenderer() {
setOpaque( true );
selectedWhiteBorder = BorderFactory.createMatteBorder(
3, 5, 3, 5, Color.white );
selectedBlackBorder = BorderFactory.createMatteBorder(
3, 5, 3, 5, Color.black );
}
/**
* Configure ourself for the state passed.
* If the value is a Color, set the background to that
* color. If not use the toString method of the value
*
**/
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus)
{
if( value instanceof Color ) {
setText( " " );
setBackground( ( Color )value );
if( isSelected ) {
if( value.equals( Color.white ) )
setBorder( selectedBlackBorder );
else
setBorder( selectedWhiteBorder );
} else {
setBorder( null );
}
} else {
setText( value.toString() );
if( isSelected ) {
setBackground( list.getSelectionBackground() );
setForeground( list.getSelectionForeground() );
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
}
return this;
}
} // ColorCellRenderer
/**
* The SelectedCheckBoxRenderer class is almost the same as the
* default check box renderer in the JTable class. However, it
* paints the cell in the normal table selected colors when it is
* selected. This avoids the white areas in the table for Boolean
* columns. Also, if all columns in the table are Boolean, you
* wouldnt be able to see the selected row using the default
* renderer!
*
* @author Mike Foley
**/
class SelectedCheckBoxRenderer extends JCheckBox
implements TableCellRenderer, Serializable {
private Border noFocusBorder;
private Color unselectedForeground;
private Color unselectedBackground;
/**
* SelectedCheckBoxRenderer, default constructor.
*
* We need to be opaque so our background color is painted.
* Create our border. Keep a reference around so it can be
* reset when we are not selected.
* Center the checkbox to match the position of the Boolean editor.
**/
public SelectedCheckBoxRenderer() {
super();
setOpaque( true );
noFocusBorder = BorderFactory.createEmptyBorder( 1, 2, 1, 2 );
setBorder( noFocusBorder );
setHorizontalAlignment( JLabel.CENTER );
}
/**
* Set the foreground color. Remember the color, so
* we can reset it when we are not selected.
*
* @param c The new foreground color.
**/
public void setForeground(Color c) {
super.setForeground(c);
unselectedForeground = c;
}
/**
* Set the background color. Remember the color, so
* we can reset it when we are not selected.
*
* @param c The new background color.
**/
public void setBackground(Color c) {
super.setBackground(c);
unselectedBackground = c;
}
/**
* Clear the foreground and background colors after
* updating the UI. This will cause the colors to be
* read from the table property portion of the UI.
**/
public void updateUI() {
super.updateUI();
setForeground( null );
setBackground( null );
}
/**
* getTableCellRendererComponent, from TableCellRenderer
*
* Configure the checkbox for the given state.
*
**/
public Component getTableCellRendererComponent( JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row, int column ) {
//
// Check or uncheck the JCheckBox.
//
setSelected((value != null && ((Boolean)value).booleanValue()));
//
// If we are selected, paint in the tables selection colors.
//
if( isSelected ) {
super.setForeground( table.getSelectionForeground() );
super.setBackground( table.getSelectionBackground() );
} else {
super.setForeground( ( unselectedForeground != null ) ?
unselectedForeground : table.getForeground() );
super.setBackground( ( unselectedBackground != null ) ?
unselectedBackground : table.getBackground() );
} // else
//
// If we have the focus, paint in the focus color for the table.
// and set the focus border.
// If not, set the no focus border.
//
if( hasFocus ) {
setBorder( UIManager.getBorder(
"Table.focusCellHighlightBorder" ) );
if (table.isCellEditable(row, column)) {
super.setForeground( UIManager.getColor(
"Table.focusCellForeground" ) );
super.setBackground( UIManager.getColor(
"Table.focusCellBackground" ) );
}
} else {
setBorder( noFocusBorder );
}
return( this );
}
} // SelectedCheckBoxRenderer
Figure 16.2 The JSplitPaneTest application window.
|