Solved

JTable question...

Posted on 1998-09-24
25
389 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
  • 16
  • 8
25 Comments
 

Author Comment

by:bjg
Comment Utility
Edited text of question
0
 
LVL 5

Expert Comment

by:msmolyak
Comment Utility
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
Comment Utility
How can I make the first column an editable JCheckBox, and the second column a non-editable JTextField?
0
 

Author Comment

by:bjg
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 5

Expert Comment

by:msmolyak
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
I tried that and it didn't work
0
 

Author Comment

by:bjg
Comment Utility
I tried that and it didn't work
0
 

Author Comment

by:bjg
Comment Utility
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
Comment Utility
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
Comment Utility
I did that and it didn't work, that's why I commented it out.
0
 
LVL 5

Expert Comment

by:msmolyak
Comment Utility
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
Comment Utility
Nope, that didn't work either.  
0
 

Accepted Solution

by:
LiliaNesterova earned 100 total points
Comment Utility
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
Comment Utility
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
Comment Utility
How can I make the JCheckBox column mutually exclusive, so that only one can be selected at a time?
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

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…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

762 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now