Showing posts with label JTable. Show all posts
Showing posts with label JTable. Show all posts

Monday, June 1, 2009

Adding a JPanel in JTable's cell

Following sample code displays a JTable with 2 rows and a sincle column.
Each cell containing a JPanel with two JButtons and each of it is linked to its own action.

PS : Setting tool tips for the buttons inside JPanel in each cell is not possible directly. It may be achieved by calculating the static position of each buttin and compare it with the mouse position and show a tooltip.


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

public class JButtonTableExample extends JFrame {

public JButtonTableExample() {
super( "JButtonTable Example" );

DefaultTableModel dm = new DefaultTableModel();
dm.setDataVector( new Object[][] { {"1" }, {"2" } }, new Object[] {"Buttons" } );

JTable table = new JTable( dm );
table.getColumn( "Buttons" ).setCellRenderer( new PanelRenderer() );
table.getColumn( "Buttons" ).setCellEditor( new PanelEditor( new JCheckBox() ) );
JScrollPane scroll = new JScrollPane( table );
table.setRowHeight( 30 );
getContentPane().add( scroll );
setSize( 400, 150 );
setVisible( true );
}

public static void main( String[] args ) {
JButtonTableExample frame = new JButtonTableExample();
frame.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e ) {
System.exit( 0 );
}
} );
}

class PanelRenderer extends JPanel implements TableCellRenderer {

public PanelRenderer() {
setOpaque( true );
init();
}

private void init() {
setLayout( new FlowLayout( FlowLayout.CENTER, 5, 0 ) );
add( new JButton( "A" ) );
add( new JButton( "B" ) );
}

public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column ) {
if ( isSelected )
{
setForeground( table.getSelectionForeground() );
setBackground( table.getSelectionBackground() );
} else
{
setForeground( table.getForeground() );
setBackground( UIManager.getColor( "Button.background" ) );
}
return this;
}
}

class PanelEditor extends DefaultCellEditor {
protected JPanel panel;

protected JButton button1;

protected JButton button2;

public PanelEditor( JCheckBox checkBox ) {
super( checkBox );
panel = new JPanel( new FlowLayout( FlowLayout.CENTER, 5, 0 ) );
button1 = new JButton( "1" );
button1.setOpaque( true );
button1.setActionCommand( "Action1" );
button1.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
JOptionPane.showMessageDialog( button1, button1.getText()
+ ": Ouch!" );
fireEditingStopped();
}
} );
button2 = new JButton( "2" );
button2.setOpaque( true );
button2.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
JOptionPane.showMessageDialog( button2, button2.getText()
+ ": Ouch!" );
fireEditingStopped();
}
} );
panel.add( button1 );
panel.add( button2 );
}

public Component getTableCellEditorComponent( JTable table, Object value, boolean isSelected, int row, int column ) {
if ( isSelected )
{
button1.setForeground( table.getSelectionForeground() );
button1.setBackground( table.getSelectionBackground() );
} else
{
button1.setForeground( table.getForeground() );
button1.setBackground( table.getBackground() );
}
return panel;
}
}
}

Monday, August 4, 2008

Override the focus traversal keys of a JTable

In a JTable, there are some predefined focus traversal keys. For example, CTRL+TAB to move out of JTable.

If that needs to be overrided with some other key combination the FocusTraversalKeySet should be replaced with a new set containing the new key combinations.

Following example shows the overriding of ForwardTraversalKey set with new KeySet containing CTRL+Z as the forward traversal key and also BackwardTraversalKey set with an EmptySet to disable all the backward traversals.


JTable table = new JTable(2,2);

TreeSet forwardSet = new TreeSet();

forwardSet.add(AWTKeyStroke.getAWTKeyStroke( KeyEvent.VK_Z,
InputEvent.CTRL_DOWN_MASK
| InputEvent.CTRL_MASK, false ) );

Set unmodifiableForwardSet =
Collections.unmodifiableSortedSet( forwardSet );

// To override the existing forward_traversal_key set
// with new unmodifiable set containing new
// key combination(CTRL+Z)
table.setFocusTraversalKeys(
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
unmodifiableForwardSet );

// To disable all the backward traversal keys,
// an empty set can be used
table.setFocusTraversalKeys(
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
Collections.EMPTY_SET );

Add rows on tabbing to a cell beyond the last cell

JTable by defaults selects the next cell when TAB is pressed. When the current selection is last cell, pressing tab selects the first cell. But here we want a new row to be inserted and selected the next newly created cell.

JTable table = new JTable(2, 2){
private final KeyStroke tabKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
AWTEvent currentEvent = EventQueue.getCurrentEvent();
if(currentEvent instanceof KeyEvent){
KeyEvent ke = (KeyEvent)currentEvent;
if(ke.getSource()!=this)
return;
// focus change with keyboard
if(rowIndex==0 && columnIndex==0
&& KeyStroke.getKeyStrokeForEvent(ke).equals(tabKeyStroke)){
((DefaultTableModel)getModel()).addRow(new Object[getColumnCount()]);
rowIndex = getRowCount()-1;
}
}
super.changeSelection(rowIndex, columnIndex, toggle, extend);
}
};

Tweaking JTable Editing

There are two client properties supported by JTable which are related to editing.

JTable.autoStartsEdit:
The value is of type Java.lang.Boolean. This property tells whether JTable should start edit when a key is types. If the value of this property is null, it defaults to Boolean.TRUE. So this feature is enabled by default in JTable.

terminateEditOnFocusLost:
The value is of type Java.lang.Boolean. This property tells whether what to do when focus goes outside of JTable. It first tries to commit the changes in editor, if can't be committed then the changes are cancelled. If the value of this property is null, it default to Boolean.FALSE. So this feature is disabled by default in JTable.

You can enable this feature as follows:

table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);


I suggest to make this feature to be enabled for JTable.

Thursday, July 31, 2008

Code to set a Jtable column to fit its contents

Code to set a column to fit its contents,


TableColumn column = table.getColumnModel().getColumn(columnIndex);
int w = column.getWidth();
int n = table.getRowCount();
for (int i = 0; i < n; i ++)
{
TableCellRenderer r = table.getCellRenderer(i, this.columnIndex);
Component c = r.getTableCellRendererComponent(
table,
table.getValueAt(i, columnIndex),
false,
false,
i,
columnIndex);
w = Math.max(w, c.getPreferredSize().width);
}
column.setPreferredWidth(w);