D
Daniel Moyne
I am trying to set a JTable with some JTables in the column1 1 and 2. I have
gone quite far but I am now facing a bug when adding a line with a selection
active in the the column where I have JTables embedded which is here column
1 and 2. Column 0 is standard.
How I proceed for cells of column 1 and 2:
- in cells I put a JPane containing the header and the Table as it is the
only possiblity to display the header when not using a JScrollPane (my
choice).
- I customize Cell and Renderer to properly display my Header and Table that
I extract from the embedded JPanels as built.
- I do a few tricks to mimick the normal behaviour when selecting normal
cells and Jtable cells as here the system does not help.
I have selected the DefaultTable Model (here) but I have also used the
AbstactModel with no more success.
I am now facing a bug when inserting a row (here at position position 0 but
same in any other position).
Everything works fine in the following conditions:
- no selection of cells before addition of row,
- selection of any cells of column 0: after addition of row at position 0
the selection remain where expected (1 row down),
but if I select a cell of any JTable cells in column 1 and 2. I have a bug
in display that I cannot fix because I do not understand what is going on.
Code is attached. Any idea would be appreciated.
CODE------------------------------
import java.lang.Math;
import java.awt.Component;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import java.awt.BorderLayout;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.AbstractCellEditor;
import javax.swing.ListSelectionModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.border.MatteBorder;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
import java.awt.Color;
import javax.swing.ImageIcon;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.UIManager;
import javax.swing.border.Border;
import java.awt.Graphics;
public class JTableInJTableDemo_object {
private static JTable myMainJTable;
private static DefaultTableModel myClassTableModel;
private Object[][] data;
private static int lineNumber=20;
private static final String[] myMainColumnNames =
{"NormalColumn","JTableColumn1","JTableColumn2"};
private static final String[] cellJTableNameColumn1 = {"Nom",
"Occurence"};
private static final String[] cellJTableNameColumn2 = {"Autre
nom", "Autre Occurence"};
private static final int cellJTableLineNumber1=2;
private static final int cellJTableLineNumber2=4;
private static final Border defaultBorder=UIManager.getBorder(new
JTable());
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("JTableInJTableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Object[][]data = new Object[lineNumber]
[myMainColumnNames.length];
buildCellJTable(lineNumber,data);
JTable myMainJTable = new JTable();
myMainJTable.setRowHeight(50);
myClassTableModel=new DefaultTableModel(data,
myMainColumnNames);
myMainJTable.setCellSelectionEnabled(false);
myMainJTable.setModel(myClassTableModel);
myMainJTable.setColumnSelectionAllowed(true);
myMainJTable.setRowSelectionAllowed(true);
myMainJTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
TableColumn columnJTable1 =
myMainJTable.getColumnModel().getColumn(1);
columnJTable1.setCellRenderer(new
MyMainJTableCellRendererForColumn1And2());
columnJTable1.setCellEditor(new
MyMainJTableCellEditor());
TableColumn columnJTable2 =
myMainJTable.getColumnModel().getColumn(2);
columnJTable2.setCellRenderer(new
MyMainJTableCellRendererForColumn1And2());
columnJTable2.setCellEditor(new
MyMainJTableCellEditor());
JScrollPane scrollPane = new JScrollPane(myMainJTable);
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);
//Create and set up the button window.
JFrame _frame = new JFrame("Jtable Action");
_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
ButtonDemo newContentPane = new ButtonDemo();
newContentPane.setOpaque(true);
_frame.setContentPane(newContentPane);
//Display the action window.
_frame.pack();
_frame.setVisible(true);
}
private static void buildCellJTable(int number,Object[][] data) {
for (int i=0;i<number;i++){
Object[] tableLine = new
Object[myMainColumnNames.length];
//we buil first line cell
tableLine[0]="line"+String.valueOf(i);
//we build second line cell
tableLine[1]=buildCell(i,cellJTableLineNumber1,cellJTableNameColumn1);
//we build third line cell
tableLine[2]=buildCell(i,cellJTableLineNumber2,cellJTableNameColumn2);
data=tableLine;
}
}
private static JPanel buildCell(int i, int jTableLineNumber,
String [] jTableNameColumn ) {
//we build cell
Object[][] jTableNameColumnData=new
Object[jTableLineNumber][jTableNameColumn.length];
Object[]jTableNameLine=new Object[jTableLineNumber];
for (int j=0;j< jTableLineNumber;j++){
for (int k=0; k< jTableNameColumn.length;k++){
jTableNameLine[j]=i+j+k;
}
jTableNameColumnData[j]=jTableNameLine;
}
JTable jTable = new JTable();
jTable.setCellSelectionEnabled(false);
DefaultTableModel jTableModel=new
DefaultTableModel(jTableNameColumnData, jTableNameColumn);
jTable.setModel(jTableModel);
for (int l=0; l<jTableNameColumn.length;l++){
jTable.setDefaultRenderer(jTable.getColumnClass(l), new
MyCellJTableCellRenderer());
}
jTable.setColumnSelectionAllowed(true);
jTable.setRowSelectionAllowed(true);
jTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JPanel jPanel=new JPanel();
jPanel.setLayout(new BorderLayout());
jPanel.add(jTable.getTableHeader(),BorderLayout.NORTH);
jPanel.add(jTable,BorderLayout.CENTER);
return jPanel;
}
static class MyMainJTableCellRendererForColumn1And2 extends JPanel
implements TableCellRenderer {
private JPanel cellJPanel;
public Component getTableCellRendererComponent(JTable
table,Object value, boolean isSelected, boolean hasFocus, int rowIndex, int
columnIndex) {
JPanel cellJPanel = (JPanel) value;
// we adjust row height
int
height=Math.max(table.getRowHeight(rowIndex), (int)
cellJPanel.getPreferredSize().getHeight());
table.setRowHeight(rowIndex,height);
return cellJPanel;
}
}
static class MyMainJTableCellEditor extends AbstractCellEditor
implements TableCellEditor {
private JPanel myCellJPanel;
@Override
public Object getCellEditorValue() {
//necessary to clear selection of cell in
jtable cell otherwise will stay
((JTable)
myCellJPanel.getComponent(1)).clearSelection();
//some people say that you can return null in
a pseudo editor but it is WRONG
return myCellJPanel;
}
public Component getTableCellEditorComponent(JTable
table, Object value, boolean isSelected, int rowIndex, int columnIndex) {
myCellJPanel = (JPanel) value;
return myCellJPanel;
}
}
static class MyCellJTableCellRenderer extends
DefaultTableCellRenderer {
private final Color matteBorderColor=null;
@Override
public Component getTableCellRendererComponent(JTable
table, Object value, boolean isSelected, boolean hasFocus,int rowIndex,int
columnIndex) {
Component c =
super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
rowIndex, columnIndex);
if (!isSelected) {
//necessary to remove focus from
unselected cell jtable
setBorder(defaultBorder);
}
return c;
}
}
/*
* ButtonDemo.java requires the following files:
*/
public static class ButtonDemo extends JPanel implements
ActionListener {
protected JButton b1;
public ButtonDemo() {
ImageIcon leftButtonIcon = null;
b1 = new JButton("Insert a row",
leftButtonIcon);
b1.setVerticalTextPosition(AbstractButton.CENTER);
b1.setHorizontalTextPosition(AbstractButton.LEADING);
b1.setMnemonic(KeyEvent.VK_D);
b1.setActionCommand("insert");
//Listen for action on button.
b1.addActionListener(this);
b1.setToolTipText("Click this button to insert
a row");
add(b1);
}
public void actionPerformed(ActionEvent e) {
if ("insert".equals(e.getActionCommand())) {
insertARow();
}
}
}
private static void insertARow() {
// (1) data creation
//we have only 3 lines
int cellJTableInsertedLineNumber=3;
Object[] tableLine = new
Object[myMainColumnNames.length];
tableLine[0]="new_line";
tableLine[1]=buildCell(0,cellJTableLineNumber1,cellJTableNameColumn1);
tableLine[2]=buildCell(0,cellJTableLineNumber2,cellJTableNameColumn2);
if (false) {
Object[][] cellJTableNameColumnData1 = new
Object[cellJTableLineNumber1][myMainColumnNames.length];
Object[]cellJTableNameLine1=new
Object[cellJTableLineNumber1];
for (int j=0;j< cellJTableLineNumber1;j++){
for (int k=0; k<
cellJTableNameColumn1.length;k++){
cellJTableNameLine1[j]=20+j+k;
}
cellJTableNameColumnData1[j]=cellJTableNameLine1;
}
JTable cellJTable = new JTable();
cellJTable.setCellSelectionEnabled(false);
DefaultTableModel myNewClassTableModel=new
DefaultTableModel(cellJTableNameColumnData1, cellJTableNameColumn1);
cellJTable.setModel(myNewClassTableModel);
for (int l=0; l<cellJTableNameColumn1.length;l++){
cellJTable.setDefaultRenderer(cellJTable.getColumnClass(l), new
MyCellJTableCellRenderer());
}
cellJTable.setColumnSelectionAllowed(true);
cellJTable.setRowSelectionAllowed(true);
cellJTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JPanel cellJPanel=new JPanel();
cellJPanel.setLayout(new BorderLayout());
cellJPanel.add(cellJTable.getTableHeader(),BorderLayout.NORTH);
cellJPanel.add(cellJTable,BorderLayout.CENTER);
tableLine[1]=cellJPanel;
}
//(2) row insertion
int insertRowIndex=0;
myClassTableModel.insertRow(insertRowIndex,tableLine);
}
}
CODE------------------------------
gone quite far but I am now facing a bug when adding a line with a selection
active in the the column where I have JTables embedded which is here column
1 and 2. Column 0 is standard.
How I proceed for cells of column 1 and 2:
- in cells I put a JPane containing the header and the Table as it is the
only possiblity to display the header when not using a JScrollPane (my
choice).
- I customize Cell and Renderer to properly display my Header and Table that
I extract from the embedded JPanels as built.
- I do a few tricks to mimick the normal behaviour when selecting normal
cells and Jtable cells as here the system does not help.
I have selected the DefaultTable Model (here) but I have also used the
AbstactModel with no more success.
I am now facing a bug when inserting a row (here at position position 0 but
same in any other position).
Everything works fine in the following conditions:
- no selection of cells before addition of row,
- selection of any cells of column 0: after addition of row at position 0
the selection remain where expected (1 row down),
but if I select a cell of any JTable cells in column 1 and 2. I have a bug
in display that I cannot fix because I do not understand what is going on.
Code is attached. Any idea would be appreciated.
CODE------------------------------
import java.lang.Math;
import java.awt.Component;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import java.awt.BorderLayout;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.AbstractCellEditor;
import javax.swing.ListSelectionModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.border.MatteBorder;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
import java.awt.Color;
import javax.swing.ImageIcon;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.UIManager;
import javax.swing.border.Border;
import java.awt.Graphics;
public class JTableInJTableDemo_object {
private static JTable myMainJTable;
private static DefaultTableModel myClassTableModel;
private Object[][] data;
private static int lineNumber=20;
private static final String[] myMainColumnNames =
{"NormalColumn","JTableColumn1","JTableColumn2"};
private static final String[] cellJTableNameColumn1 = {"Nom",
"Occurence"};
private static final String[] cellJTableNameColumn2 = {"Autre
nom", "Autre Occurence"};
private static final int cellJTableLineNumber1=2;
private static final int cellJTableLineNumber2=4;
private static final Border defaultBorder=UIManager.getBorder(new
JTable());
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("JTableInJTableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Object[][]data = new Object[lineNumber]
[myMainColumnNames.length];
buildCellJTable(lineNumber,data);
JTable myMainJTable = new JTable();
myMainJTable.setRowHeight(50);
myClassTableModel=new DefaultTableModel(data,
myMainColumnNames);
myMainJTable.setCellSelectionEnabled(false);
myMainJTable.setModel(myClassTableModel);
myMainJTable.setColumnSelectionAllowed(true);
myMainJTable.setRowSelectionAllowed(true);
myMainJTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
TableColumn columnJTable1 =
myMainJTable.getColumnModel().getColumn(1);
columnJTable1.setCellRenderer(new
MyMainJTableCellRendererForColumn1And2());
columnJTable1.setCellEditor(new
MyMainJTableCellEditor());
TableColumn columnJTable2 =
myMainJTable.getColumnModel().getColumn(2);
columnJTable2.setCellRenderer(new
MyMainJTableCellRendererForColumn1And2());
columnJTable2.setCellEditor(new
MyMainJTableCellEditor());
JScrollPane scrollPane = new JScrollPane(myMainJTable);
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);
//Create and set up the button window.
JFrame _frame = new JFrame("Jtable Action");
_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
ButtonDemo newContentPane = new ButtonDemo();
newContentPane.setOpaque(true);
_frame.setContentPane(newContentPane);
//Display the action window.
_frame.pack();
_frame.setVisible(true);
}
private static void buildCellJTable(int number,Object[][] data) {
for (int i=0;i<number;i++){
Object[] tableLine = new
Object[myMainColumnNames.length];
//we buil first line cell
tableLine[0]="line"+String.valueOf(i);
//we build second line cell
tableLine[1]=buildCell(i,cellJTableLineNumber1,cellJTableNameColumn1);
//we build third line cell
tableLine[2]=buildCell(i,cellJTableLineNumber2,cellJTableNameColumn2);
data=tableLine;
}
}
private static JPanel buildCell(int i, int jTableLineNumber,
String [] jTableNameColumn ) {
//we build cell
Object[][] jTableNameColumnData=new
Object[jTableLineNumber][jTableNameColumn.length];
Object[]jTableNameLine=new Object[jTableLineNumber];
for (int j=0;j< jTableLineNumber;j++){
for (int k=0; k< jTableNameColumn.length;k++){
jTableNameLine[j]=i+j+k;
}
jTableNameColumnData[j]=jTableNameLine;
}
JTable jTable = new JTable();
jTable.setCellSelectionEnabled(false);
DefaultTableModel jTableModel=new
DefaultTableModel(jTableNameColumnData, jTableNameColumn);
jTable.setModel(jTableModel);
for (int l=0; l<jTableNameColumn.length;l++){
jTable.setDefaultRenderer(jTable.getColumnClass(l), new
MyCellJTableCellRenderer());
}
jTable.setColumnSelectionAllowed(true);
jTable.setRowSelectionAllowed(true);
jTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JPanel jPanel=new JPanel();
jPanel.setLayout(new BorderLayout());
jPanel.add(jTable.getTableHeader(),BorderLayout.NORTH);
jPanel.add(jTable,BorderLayout.CENTER);
return jPanel;
}
static class MyMainJTableCellRendererForColumn1And2 extends JPanel
implements TableCellRenderer {
private JPanel cellJPanel;
public Component getTableCellRendererComponent(JTable
table,Object value, boolean isSelected, boolean hasFocus, int rowIndex, int
columnIndex) {
JPanel cellJPanel = (JPanel) value;
// we adjust row height
int
height=Math.max(table.getRowHeight(rowIndex), (int)
cellJPanel.getPreferredSize().getHeight());
table.setRowHeight(rowIndex,height);
return cellJPanel;
}
}
static class MyMainJTableCellEditor extends AbstractCellEditor
implements TableCellEditor {
private JPanel myCellJPanel;
@Override
public Object getCellEditorValue() {
//necessary to clear selection of cell in
jtable cell otherwise will stay
((JTable)
myCellJPanel.getComponent(1)).clearSelection();
//some people say that you can return null in
a pseudo editor but it is WRONG
return myCellJPanel;
}
public Component getTableCellEditorComponent(JTable
table, Object value, boolean isSelected, int rowIndex, int columnIndex) {
myCellJPanel = (JPanel) value;
return myCellJPanel;
}
}
static class MyCellJTableCellRenderer extends
DefaultTableCellRenderer {
private final Color matteBorderColor=null;
@Override
public Component getTableCellRendererComponent(JTable
table, Object value, boolean isSelected, boolean hasFocus,int rowIndex,int
columnIndex) {
Component c =
super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
rowIndex, columnIndex);
if (!isSelected) {
//necessary to remove focus from
unselected cell jtable
setBorder(defaultBorder);
}
return c;
}
}
/*
* ButtonDemo.java requires the following files:
*/
public static class ButtonDemo extends JPanel implements
ActionListener {
protected JButton b1;
public ButtonDemo() {
ImageIcon leftButtonIcon = null;
b1 = new JButton("Insert a row",
leftButtonIcon);
b1.setVerticalTextPosition(AbstractButton.CENTER);
b1.setHorizontalTextPosition(AbstractButton.LEADING);
b1.setMnemonic(KeyEvent.VK_D);
b1.setActionCommand("insert");
//Listen for action on button.
b1.addActionListener(this);
b1.setToolTipText("Click this button to insert
a row");
add(b1);
}
public void actionPerformed(ActionEvent e) {
if ("insert".equals(e.getActionCommand())) {
insertARow();
}
}
}
private static void insertARow() {
// (1) data creation
//we have only 3 lines
int cellJTableInsertedLineNumber=3;
Object[] tableLine = new
Object[myMainColumnNames.length];
tableLine[0]="new_line";
tableLine[1]=buildCell(0,cellJTableLineNumber1,cellJTableNameColumn1);
tableLine[2]=buildCell(0,cellJTableLineNumber2,cellJTableNameColumn2);
if (false) {
Object[][] cellJTableNameColumnData1 = new
Object[cellJTableLineNumber1][myMainColumnNames.length];
Object[]cellJTableNameLine1=new
Object[cellJTableLineNumber1];
for (int j=0;j< cellJTableLineNumber1;j++){
for (int k=0; k<
cellJTableNameColumn1.length;k++){
cellJTableNameLine1[j]=20+j+k;
}
cellJTableNameColumnData1[j]=cellJTableNameLine1;
}
JTable cellJTable = new JTable();
cellJTable.setCellSelectionEnabled(false);
DefaultTableModel myNewClassTableModel=new
DefaultTableModel(cellJTableNameColumnData1, cellJTableNameColumn1);
cellJTable.setModel(myNewClassTableModel);
for (int l=0; l<cellJTableNameColumn1.length;l++){
cellJTable.setDefaultRenderer(cellJTable.getColumnClass(l), new
MyCellJTableCellRenderer());
}
cellJTable.setColumnSelectionAllowed(true);
cellJTable.setRowSelectionAllowed(true);
cellJTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JPanel cellJPanel=new JPanel();
cellJPanel.setLayout(new BorderLayout());
cellJPanel.add(cellJTable.getTableHeader(),BorderLayout.NORTH);
cellJPanel.add(cellJTable,BorderLayout.CENTER);
tableLine[1]=cellJPanel;
}
//(2) row insertion
int insertRowIndex=0;
myClassTableModel.insertRow(insertRowIndex,tableLine);
}
}
CODE------------------------------