Solved

JTable question...

Posted on 1998-09-24
25
420 Views
Last Modified: 2008-02-20
I am trying to create a JTable which has two columns.  The first column I want to be a JCheckBox (and I want the user to be able to set it checked or unchecked in the table as well as display the cell checked or unchecked depending on the data set that the model contains).  The second column I want to have a JTextField as the CellRenderer but I don't want it to be editable, so it's not a CellEditor, just a CellRenderer.  I also do not want to display the column headers.  How can I do this?
0
Comment
Question by:bjg
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 16
  • 8
25 Comments
 

Author Comment

by:bjg
ID: 1224926
Edited text of question
0
 
LVL 5

Expert Comment

by:msmolyak
ID: 1224927
This is an example of such a table:

        String[] columnNames = {DIRECTORY, FILE_SPEC, IS_RECURSIVE, PARSER_START_STATE, URL_PREFIX};
        DefaultTableModel model = new DefaultTableModel(columnNames, 0)
        {
            public Class getColumnClass(int columnIndex)
            {
                if (columnIndex == 2) // This makes the third column  displayed as a checkbox
                {
                    return (new Boolean(true)).getClass();
                }
                else
                {
                    return super.getColumnClass(columnIndex); // Other columns are labels
                }
            }
        };

        JTable newTable = new JTable(model)
        {
          public boolean isCellEditable(int row, int column)
          {
            return (column != 1);  // This makes the second column non-editable
          }
        };

        newTable.setTableHeader(null); // That should take care of the header
0
 

Author Comment

by:bjg
ID: 1224928
How can I make the first column an editable JCheckBox, and the second column a non-editable JTextField?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:bjg
ID: 1224929
Do I have to create a custom CellRenderer, and a custom CellEditor, and then set each column's editor or renderer appropriately?
0
 
LVL 5

Expert Comment

by:msmolyak
ID: 1224930
Simply replace the literal 2 with literal 0 in the code above. And shorten the list of column names to two entries. The rest stays the same.
0
 

Author Comment

by:bjg
ID: 1224931
Do I have to create a custom CellRenderer, and a custom CellEditor, and then set each column's editor or renderer appropriately?
0
 

Author Comment

by:bjg
ID: 1224932
How do I make the other columns JTextFields, rather than JLabels?
I want to support multiple lines of text for each cell (not the JCheckBox cell, but the JTextField cell)
0
 

Author Comment

by:bjg
ID: 1224933
How do I make the other columns JTextFields, rather than JLabels?
I want to support multiple lines of text for each cell (not the JCheckBox cell, but the JTextField cell)
0
 
LVL 5

Expert Comment

by:msmolyak
ID: 1224934
No, just try the code I supplied, no ther changes should be required. DefaultTableModel and DefaultCellRenderer should take care of all the details.
0
 
LVL 5

Expert Comment

by:msmolyak
ID: 1224935
If the cell is editable, it will use JTextField a cell editor. I am not sure with multiple lines of text, that will probably require a custom renderer/editor.
0
 

Author Comment

by:bjg
ID: 1224936
How do I make the other columns JTextFields, rather than JLabels?
I want to support multiple lines of text for each cell (not the JCheckBox cell, but the JTextField cell)
0
 

Author Comment

by:bjg
ID: 1224937
I don't want the JTextField cell to be editable, I want the JCheckBox field to be editable or selectable.  The only reason why I want to use the JTextField as the other cell, is so I can support multiple lines of text.  How can I set this up in the table?
0
 
LVL 5

Expert Comment

by:msmolyak
ID: 1224938
I see what you want. Yes, if you want to have a text field as a renderer you have to create one of your own. I am not sure how it solves your problem, beacuse text field as far as I know display only one line of text.

Look at the code of DefaultTableCellRenderer (which extends JLabel) and create something similar by extending JTextField. (Make sure you call setEditable(false)). I think it will look no diffrenet that it looks with the label, but you can try.

To set the new cell editor only for specific column, get a TableColumn object for the desired column and call setCellRenderer().
0
 

Author Comment

by:bjg
ID: 1224939
Well, I finally have most of it working.  I have it working how I want, just not looking how I want.  When I tell the first column to be a Boolean and editable, it results in a cell with a selectable checkbox.  This is what I want.  But the default look of the checkbox is centered in the cell, and it does not highlight when you select the row.  How can I change this so that it is in the upper left of the cell and highlights like the rest of the row?
0
 
LVL 5

Expert Comment

by:msmolyak
ID: 1224940
You can change the way check box looks by extending DefaultCellEditor class and overriding getTableCellEditorComponent() method. In that method first check whether editorComponent is a check box (it is a protected member so you can do it). If it is, change its appearance, then call super.getTableCellEditorComponent().
0
 

Author Comment

by:bjg
ID: 1224941
I tried that and it didn't work
0
 

Author Comment

by:bjg
ID: 1224942
I tried that and it didn't work
0
 

Author Comment

by:bjg
ID: 1224943
If I set a custom Editor for the CheckBox column, it only shows that renderer when I select the JCheckBox, and then it shows the default renderer for the CheckBox column after I have selected it.  If I also set a custom renderer, I can't select and deselect the JCheckBox.  How can I get this to work?

Here is my code:

package Lccs.Gui.Awt;

import com.sun.java.swing.*;
import com.sun.java.swing.border.*;
import com.sun.java.swing.table.*;
import java.awt.*;
import java.util.*;

public class CheckBoxTable extends JTable
{
      
    public CheckBoxTable(Object data[][])
    {
        super();
       
        this.data = data;
       
        verifyDataElements();
       
          setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
          setShowHorizontalLines(true);
        setShowVerticalLines(false);
       
        String columns[];
        if (hasCheckBox)
        {
              columns = new String[2];
              columns[0] = "Selection";
              columns[1] = "Information";
        } else
        {
              columns = new String[1];
              columns[0] = "Information";
        }
       
        tableModel = new InnerTableModel(columns, data);
        setModel(tableModel);
       
        setDefaultRenderer(Object.class, new InnerTextFieldCellRenderer());
        //setDefaultRenderer(Boolean.class, new InnerCheckBoxCellRenderer());
        setDefaultEditor(Boolean.class, new InnerCellEditor());

            if (hasCheckBox)
            {
                  TableColumn col = getColumn(columns[0]);
                  col.setWidth(30);
                  col.setMinWidth(30);
                  col.setMaxWidth(30);
            }
            
            setRowHeight(getMeasuredRowHeight());
       
        setTableHeader(null);
        setCellSelectionEnabled(false);
    }
   
    private void verifyDataElements() throws IllegalArgumentException
    {
        if (data[0].length > 1)
        {
              for (int i = 0; i < data.length; i++)
              {
                    if (!(data[i][0] instanceof Boolean))
                    {
                          throw new IllegalArgumentException(
                                "First element of row must be a Boolean Object." );
                    }
              }
                hasCheckBox = true;
        } else
              hasCheckBox = false;
    }
   
    private int getMeasuredRowHeight()
    {
          int tokenCount = 0;
          for (int i = 0; i < data.length; i++)
          {
                String str = null;
                if (hasCheckBox)
                      str = (String)data[i][1];
                else
                      str = (String)data[i][0];
                StringTokenizer tok = new StringTokenizer(str, "\n");
                tokenCount = tok.countTokens();
          }
          return (20 * tokenCount);
    }
   
    public void setData(Object data[][])
    {
          tableModel.setData(data);
          revalidate();
          repaint();
    }
   
   
    //Inner Class - TableModel
      class InnerTableModel extends AbstractTableModel
      {
          String[] columnNames = null;
          Object[][] data = null;

          public InnerTableModel(String columns[], Object data[][])
          {
              this.columnNames = columns;
              this.data = data;
          }

          public void setData(Object newData[][])
          {
                this.data = newData;
          }

          public int getColumnCount()
          {
              return columnNames.length;
          }

          public int getRowCount()
          {
              return data.length;
          }

          public String getColumnName(int col)
          {
              return columnNames[col];
          }

          public Object getValueAt(int row, int col)
          {
              return data[row][col];
          }

          public Class getColumnClass(int c)
          {
              return getValueAt(0, c).getClass();
          }

          public boolean isCellEditable(int row, int col)
          {
                if (hasCheckBox)
                {
                      if (col == 0)
                            return true;
                }
                return false;
          }

          public void setValueAt(Object value, int row, int col)
          {
              data[row][col] = value;
          }

      }
   
   
   
      //Inner Class - TableCellRenderer
      class InnerTextFieldCellRenderer extends JTextField implements
                                                  TableCellRenderer
      {
          public InnerTextFieldCellRenderer()
          {
                super();
                setOpaque(true);
                setEditable(false);
                setBorder(new EmptyBorder(0,5,0,5));
          }

          public Component getTableCellRendererComponent(JTable table, Object value,
                                boolean isSelected, boolean hasFocus, int row, int column)
          {
                if (isSelected)
              {
                  setForeground(SystemColor.textHighlightText);
                  setBackground(SystemColor.textHighlight);
              }
              else
              {
                  setBackground(table.getBackground());
                  setForeground(table.getForeground());
              }
                setFont(table.getFont());

                if (value != null)
                {
                      setText(value.toString());
                }

                return this;
          }
      }      //End Inner Class
      
      //Inner Class - TableCellRenderer
      class InnerCheckBoxCellRenderer extends JCheckBox implements
                                                  TableCellRenderer
      {
          public InnerCheckBoxCellRenderer()
          {
                super();
                setOpaque(true);
                setVerticalAlignment(TOP);
                setHorizontalAlignment(LEFT);
          }

          public Component getTableCellRendererComponent(JTable table, Object value,
                                boolean isSelected, boolean hasFocus, int row, int column)
          {

                  if (isSelected)
              {
                  setForeground(SystemColor.textHighlightText);
                  setBackground(SystemColor.textHighlight);
              }
              else
              {
                  setBackground(table.getBackground());
                  setForeground(table.getForeground());
              }
              
                return this;
          }
      }      //End Inner Class
      
      class InnerCellEditor extends DefaultCellEditor
      {
            InnerCellEditor()
            {
                  super(new JCheckBox());
            }
            
            public Component getTableCellEditorComponent(JTable table, Object value,
                                     boolean isSelected,
                                     int row, int column)
            {

                  ((JCheckBox)editorComponent).setVerticalAlignment(JCheckBox.TOP);
                ((JCheckBox)editorComponent).setHorizontalAlignment(JCheckBox.LEFT);
                  
                  if (isSelected)
                  {
                      editorComponent.setBackground(SystemColor.textHighlightText);
                      editorComponent.setForeground(SystemColor.textHighlight);
                  }
                  else
                  {
                      editorComponent.setBackground(table.getBackground());
                      editorComponent.setForeground(table.getForeground());
                  }

                  return editorComponent;
          }
      }
      
      private boolean                  hasCheckBox;
      private InnerTableModel      tableModel;
      private Object                   data[][];
}

0
 
LVL 5

Expert Comment

by:msmolyak
ID: 1224944
Yes, you should be defining you custome renderer as well. Try setting it using:

table.setDefaultRenderer(Boolean.TYPE, new InnerCheckBoxCellRenderer());

0
 

Author Comment

by:bjg
ID: 1224945
I did that and it didn't work, that's why I commented it out.
0
 
LVL 5

Expert Comment

by:msmolyak
ID: 1224946
Sorry, I missed it. What if you disable the check box in your renderer. The problem might stem from the fact that checkbox component used as a renderer receives the mouse events instead of the table.
0
 

Author Comment

by:bjg
ID: 1224947
Nope, that didn't work either.  
0
 

Accepted Solution

by:
LiliaNesterova earned 100 total points
ID: 1224948
Hello, bjg,

You can do for example:

JTable jTableQuestion;
String[] columnNames={"checkColumn","readOnlyColumn"}; //you can specify your columns' names

com.sun.java.swing.table.TableModel dataModelQuestion =
    new com.sun.java.swing.table.DefaultTableModel(columnNames,10) {
      public boolean isCellEditable(int row, int col)
                 {
                         return (col!=1); //you can't edit the second column of the table
                }
      public Class getColumnClass(int col) {
        if (col==0)
           return Boolean.class; //for that column class the default column editor is an instance of JCheckBox
        return String.class; //for other columns we use JTextField
      }

    };
    jTableQuestion = new JTable(dataModelQuestion);

    jTableQuestion.setTableHeader(null); //no header

You can use another constructor of DefaultTableModel that better fits your needs.

But there are so many versions of Swing and you may have problems.

Buy,
Lilia

0
 

Author Comment

by:bjg
ID: 1224949
I guess you answered my original question, but I already have that part working.  I am just trying to set a custom cell editor and cell renderer for the boolean (JCheckBox) column of the table because I don't like the default look of the JCheckBox in the center, I want the JCheckBox in the upper left hand corner.  So how do I do that?
0
 

Author Comment

by:bjg
ID: 1224950
How can I make the JCheckBox column mutually exclusive, so that only one can be selected at a time?
0

Featured Post

Optimize your web performance

What's in the eBook?
- Full list of reasons for poor performance
- Ultimate measures to speed things up
- Primary web monitoring types
- KPIs you should be monitoring in order to increase your ROI

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
In this post we will learn different types of Android Layout and some basics of an Android App.
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
Suggested Courses

615 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question