Performance of JTable as renderer

I have a table that contains tables as cells.
Quite similiar to DefaultTableCellRenderer I extended JTable and used return the object itself as renderer.
However the performance is sucks, for example while scrolling. I tried to copy the implementation notes for DefaultTableCellRenderer but the display gets screwed up.
What is the correct & efficient way to render tables within tables?
How can improve the performance?
lo

Hi again,
seems that you have transferred your problem to me - can't sleep before posting this:
The performance problem with your design is as follows: In the moment the "inner" table is longer than the height of the viewport, the hole table has to be rerendered when you scroll because it is one cell and rerendered in hole. So not only the fields, that are unvisible before will be rerendered but all the visible ones too. - That is fatal and I see no way to bring this design of tables in table to a better performance.
But you can keep the look of it - I thought about this - you can implement the same look and feel by a single table - but you have to use an own TableDataModel for it, that simulates several tables regardless the fact, it is only one JTable - the different headers can be done by the cellrender, except the top-headers, that go over more than one column - they must be provided by a JPanel with JLabels in it on the top of the table - you have to keep track that the columns of an inner table stick together even when the user track them to another position. There are many things to do and to worry about, but it can be done and it will be as fast as every normal JTable.
To say it clear - table 1 is for example from column 0..1, table 2 from 2...4 and so on - but it is not stored this way in the datamodel - there are different tabledata in different "tables" - they can be sorted without effect to the other tables - the plain column,row address from the JTable must be translated in a table,column,row address in the datamodel - that is not so difficult as it looks perhaps, only the way you look at your data is different from that, stored in the datamodel.
I got this idea during a walk in the snowy park outside - hope, I can sleep yet.
See you tomorrow
greetings Marsian

Similar Messages

  • Dynamic JTable and rendering column as JComboBox

    I originally posted this to the "Java Programming" topic, but it was suggested that I move it over here.
    I'm new to cell renderers and editors, so I'm hoping someone can put me on the right path.
    I've got a JTable that is initially empty. I've set one column to use a custom cell renderer that extends JComboBox and implements TableCellRenderer.
    The user can add rows to the table at any time, I'm using TableModel.addRow() for this. When I call addRow, I pass the entryies for the JComboBox column as a String[], with one array element for each entry in the JComboBox.
    In my custom renderer, I take the values from the array and use JComboBox.addItem() to add them to the JComboBox.
    When I run the code, it appears fine, but the JComboBox doesn't function, i.e. it is not editable (yes, the column is set as editable). I assume I need to add a custom editor. I tried
    table.setCellEditor(new DefaultCellEditor(ComboBoxCellRenderer);
    and the combobox was now editable, but it was empty and I got nullpointer exceptions.
    What am I missing?
    Any help is appreciated. Here is what I'm trying:
    **************** Constructing the table **************
    DefaultTableModel tablemodel = new DefaultTableModel(columnnames,0);
    datasourcestable = new JTable(tablemodel) ;
    // Set custom renderer for particular columns in this JTable
    ComboBoxCellRenderer renderer = new ComboBoxCellRenderer();
    TableColumn waveformscalarcolumn = datasourcestable.getColumnModel().getColumn(datasourcestable.getColumn("Title").getModelIndex());
    waveformscalarcolumn.setCellRenderer(renderer);
    // tried the following, combobox becomes editable but empty
    //waveformscalarcolumn.setCellEditor(new DefaultCellEditor(renderer));
    *************** Adding rows to the table (Event Code)*********************
    DefaultTableModel tablemodel = (DefaultTableModel)datasourcestable.getModel();
    Object[] rowdata = new Object[3];
    rowdata[0] = "gaga";
    String[] cboxentries = {"cbox entry 1","cbox entry 2"};
    rowdata[1] = cboxentries;
    rowdata[1] = "gaga"'
    tablemodel.addRow(rowdata);
    **************** Custom Cell Renderer **********************
    class ComboBoxCellRenderer extends JComboBox implements TableCellRenderer {
    public ComboBoxCellRenderer() {
    setOpaque(true);
    public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus, int row, int column) {
    String[] stringarray = (String[]) value;
    for (int i=0; i<stringarray.length; i++){
    this.addItem(stringarray);
    return this;
    }

    Ah! Using the ArrayList of editors in getCellEditor() is very clever, that's the solution I couldn't come up with. Now I just have to remember to add and delete editors as I add and delete rows.
    Thanks, I've got everything working now. Here's are some code snippets, for anyone interested. I used Vector rather than ArrayList to be thread safe.
    // ******************* Global variables ***********
    Vector<TableCellEditor> editors = new Vector<TableCellEditor>(24,8);
    JTable table;
    // *************** construct table ****************
    DefaultTableModel tablemodel = new DefaultTableModel(columnnames,0);
    table = new JTable(tablemodel) {
         public TableCellEditor getCellEditor(int row,int col) {
              int modelcolumn = convertColumnIndexToModel(col);
              int fancycol = table.getColumn("Title").getModelIndex();
              if (modelcolumn == fancycol) {
                   return (TableCellEditor)editors.elementAt(row);
              } else {
                   return super.getCellEditor(row,col);
    // Set custom renderer for particular column in this JTable
    ComboBoxCellRenderer comboboxrenderer = new ComboBoxCellRenderer();
    TableColumn column = table.getColumnModel().getColumn(table.getColumn("Title").getModelIndex());
    column.setCellRenderer(comboboxrenderer);
    //*************** Adding rows to the table (Event Code)*********************
    DefaultTableModel tablemodel = (DefaultTableModel)table.getModel();
    Object[] rowdata = new Object[3];
    rowdata[0] = "gaga";
    String[] cboxentries = {"cbox entry 1","cbox entry 2"};
    JComboBox cellcombo = new JComboBox();
    cellcombo.addItem(cboxentries[0]);
    cellcombo.addItem(cboxentries[1]);
    DefaultCellEditor editor = new DefaultCellEditor(cellcombo);
    editors.add(editor);
    rowdata[1] = cellcombo.getItemAt(0);          // don't know if this matters
    rowdata[2] = "gaga2";
    tablemodel.addRow(rowdata);
    //**************** Custom Cell Renderer *********************
    class ComboBoxCellRenderer extends JComboBox implements TableCellRenderer {
         public ComboBoxCellRenderer() {
         public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus, int row, int column) {
    // display value in our JComboBOx
              this.addItem(value);
              this.setSelectedItem(value);
              return this;
    }

  • How do you measure performance of an item renderer?

    I'm creating an ItemRenderer in Flex 4.6 and I want to know how to measure total time to create, view and render an item renderer and how long it takes to view and render that item renderer when it's being reused.
    I just watched the video, Performance Tips and Tricks for Flex and Flash Development and it describes the creation time, validation time and render time and also the reset time. This is described at 36:43 and 40:25.
    I'm looking for a way to get numbers in milliseconds for total item renderer render time and reset time (what is being done in the video). 

    To answer your first question, in this video Ryan Frishberg recommends measuring and tuning your code. I'm trying to follow his example for my own item renderers.
    I've taken some key slides out to show you.

  • Multi threading race condition in JTable while rendering and truncating?

    Hi All,
    It seems that there is a race confition when rendering a large table which is truckated by another thread while rendering it on a JTable view.
    Let me try to explain what I think is the problem:
    When considering the folowing code from BasicTableUI
    First the size of the tbale model is determined in
    public void paint(Graphics g, JComponent c) {
    [snip]
            if (rMax == -1) {
             rMax = table.getRowCount()-1;
            }then this cMax is passed to:
    private void paintCells(Graphics g, int rMin, int rMax, int cMin, int cMax) {
         JTableHeader header = table.getTableHeader();
         TableColumn draggedColumn = (header == null) ? null : header.getDraggedColumn();
         TableColumnModel cm = table.getColumnModel();
         int columnMargin = cm.getColumnMargin();
            Rectangle cellRect;
         TableColumn aColumn;
         int columnWidth;
         if (table.getComponentOrientation().isLeftToRight()) {
             for(int row = rMin; row <= rMax; row++) {
              cellRect = table.getCellRect(row, cMin, false);
                    for(int column = cMin; column <= cMax; column++) {
                        aColumn = cm.getColumn(column);
                        columnWidth = aColumn.getWidth();
                        cellRect.width = columnWidth - columnMargin;
                        if (aColumn != draggedColumn) {
                            paintCell(g, cellRect, row, column);
                        cellRect.x += columnWidth;
         } else {The prepareRenderer works like this:
        public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
            Object value = getValueAt(row, column);
    [snip]
         return renderer.getTableCellRendererComponent(this, value,
                                                       isSelected, hasFocus,
                                                       row, column);
        }Here the above getValueAt is called for every cell to be rendered (in one thread) , while async a row can be deleted (in another thread) while the tables rendereing is still in progress. This leads to a value to be unexpectedly be null in the above return renderer.getTableCellRendererComponent method call: this method could return an empty panel to indicated that the cell is gone which is strange behaviour because the row doesn't exists anymore. The other option would be to return a null renderer so that the cell won't be rendered but that is impossible because the code doens't expect a null renderer. The third option could to be synchronize somehow the 2 threads so that any delete on the model has to wait until the rendering has finished.
    A possble solution could be to make paintCells at least protected and change to code to see if the designated row still exists, and if not don't increment the row height
    Any help/feedback is greatly appreciated!
    Note that this question is based upon Java5 and I do not know if this is also true for Java6
    Thnx
    Andr'e

    So this means that a TableModel must be manupulated (setValueAt , adding deleting and/or updating objects in this TableModel) through a thread in the EventQueue!
    i.e. (pseudo code)
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    getTableModel().setValueAt(........)
            });A

  • Problem in JTable cell renderer

    Hi
    One problem in JTable cell. Actually I am using two tables while I am writing renderer for word raping in first table .. but it is affected in last column only remain is not being effected�. Please chaek it out what is exact I am missing�
    Thanks
    package com.apsiva.tryrowmerge;
    import java.awt.*;
    import java.awt.event.*;
    import java.util.ArrayList;
    import java.util.EventObject;
    import java.util.Hashtable;
    import java.net.*;
    import javax.swing.*;
    import javax.swing.border.Border;
    import javax.swing.border.EmptyBorder;
    import javax.swing.event.*;
    import javax.swing.table.TableCellEditor;
    import javax.swing.table.TableCellRenderer;
    import javax.swing.table.TableColumn;
    class Item_Details extends JFrame {
        ApsJTable itemTable = null;
         ApsJTable imageTable = null;     
         ArrayList data = new ArrayList();
         String[] columns = new String[2];
         ArrayList data1 = new ArrayList();
         String[] columns1 = new String[2];
         ItemTableModel itemTableModel = null;
         ItemTableModel itemTableModel1 = null;
         public Item_Details()
              super("Item Details");          
             this.setSize(600,100);
             this.setBackground(Color.WHITE);
              this.setVisible(true);
             init();          
         private void init(){
              ////////////// Get data for first Table Model  ////////////////////////////
              data = getRowData();
              columns = getColData();
              System.out.println(columns[0]);
             itemTableModel = new ItemTableModel(data,columns);
             /////////////Get Data for Second Table Model //////////////////////////////
              try{
                        data1 = getRowData1();
                 }catch(Exception e){}
              columns1 = getColumns1();
             itemTableModel1 = new ItemTableModel(data1,columns1);
             ///////////// Set Data In Both Table Model //////////////////////////////////
              itemTable = new ApsJTable(itemTableModel);
              imageTable = new ApsJTable(itemTableModel1);
              this.itemTable.setShowGrid(false);
              this.imageTable.setShowGrid(false);
              this.itemTable.setColumnSelectionAllowed(false);
              this.imageTable.setColumnSelectionAllowed(false);
              System.out.println(itemTable.getColumnCount());
              this.imageTable.setRowHeight(getImageHeight()+3);
              JScrollPane tableScrollPane = new JScrollPane(this.imageTable,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
              tableScrollPane.setRowHeaderView(this.itemTable);
              //itemTable.getColumnModel().getColumn(0).setMaxWidth(200);
              itemTable.getColumnModel().getColumn(0).setPreferredWidth(200);
              itemTable.getColumnModel().getColumn(1).setPreferredWidth(600);
              tableScrollPane.getRowHeader().setPreferredSize(new Dimension(800, 0));
              itemTable.getTableHeader().setResizingAllowed(false);
              itemTable.getTableHeader().setReorderingAllowed(false);
              itemTable.setColumnSelectionAllowed(false);
              //itemTable.setRowHeight(25);
              itemTable.setCellSelectionEnabled(false);
              itemTable.setFocusable(false);
              imageTable.getTableHeader().setReorderingAllowed(false);
              imageTable.setFocusable(false);
              imageTable.setCellSelectionEnabled(false);
              //tableScrollPane.setOpaque(false);
              itemTable.setAutoCreateColumnsFromModel(false);
              int columnCount = itemTable.getColumnCount();
              for(int k=0;k<columnCount;k++)
                   TableCellRenderer renderer = null;
                   TableCellEditor editor = null;
                   renderer = new TextAreaCellRenderer();     // NEW
              //     editor = new TextAreaCellEditor();     
              //     TableColumn column = new TableColumn(k,itemTable.getColumnModel().getColumn(k).getWidth(),renderer, editor);
                   System.out.println(k);
                   itemTable.getColumnModel().getColumn(k).setCellRenderer(renderer);          
                   //itemTable.getColumnModel().getColumn(k).setCellEditor(editor);
                   /*itemTable.getColumnModel().getColumn(1).setCellRenderer(new TextAreaCellRenderer());
                   itemTable.getColumnModel().getColumn(1).setCellEditor(new TextAreaCellEditor());*/
    //               itemTable.setShowGrid(false);
                   //itemTable.addColumn(column);
                   //itemTable.getColumnModel().getColumn(k).setCellRenderer(new MultiLineCellRenderer());
                   //itemTable.getColumnModel().getColumn(k).setCellEditor(new TextAreaCellEditor());
    ////////////---------------------- Here background color is being set--------------//////////////////
              this.imageTable.getParent().setBackground(Color.WHITE);
              this.itemTable.getParent().setBackground(Color.WHITE);
              tableScrollPane.setCorner(ScrollPaneConstants.UPPER_LEFT_CORNER,this.itemTable.getTableHeader());
              getContentPane().add(tableScrollPane,BorderLayout.CENTER);
              getContentPane().setVisible(true);
         public static void main(String[] str){
              com.incors.plaf.alloy.AlloyLookAndFeel.setProperty("alloy.licenseCode", "2005/05/28#[email protected]#1v2pej6#1986ew");
              try {
                javax.swing.LookAndFeel alloyLnF = new com.incors.plaf.alloy.AlloyLookAndFeel();
                javax.swing.UIManager.setLookAndFeel(alloyLnF);
              } catch (javax.swing.UnsupportedLookAndFeelException ex) {
              ex.printStackTrace();
              Item_Details ID = new Item_Details();
              ID.setVisible(true);
    public ArrayList getRowData()
         ArrayList rowData=new ArrayList();
         Hashtable item = new Hashtable();
         item.put(new Long(0),new String("Item No:aaaaaaa aaaaaaaa aaaaaaaaa aaaaaa"));
         item.put(new Long(1),new String("RED-1050"));
         rowData.add(0,item);
         item = new Hashtable();
         item.put(new Long(0),new String("Description:rt r trtrt rttrytrr tytry trytry tr tr rty thyjyhjhnhnhgg hhjhgjh"));
         item.put(new Long(1),new String("SYSTEM 18 mbh COOLING 13 mbh HEATING 230/208 v POWER AIRE "));
         rowData.add(1,item);
         item = new Hashtable();
         item.put(new Long(0),new String("Stage:"));
         item.put(new Long(1),new String("Draft"));
         rowData.add(2,item);
         item = new Hashtable();
         item.put(new Long(0),new String("Price: "));
         item.put(new Long(1),new String("999.00"));
         rowData.add(3,item);
         item = new Hashtable();
         item.put(new Long(0),new String("Features:"));
         item.put(new Long(1),new String("SYSTEM COOLING & HEATING 12 mbh 230/208 v POWER AIRE SYSTEM1234 COOLING & HEATING 12 mbh 230/208 v POWER AIRE "));
         rowData.add(4,item);
         item = new Hashtable();
         item.put(new Long(0),new String("Features:"));
         item.put(new Long(1),new String("SYSTEM COOLING & HEATING 12 mbh 230/208 v POWER AIRE SYSTEM1234 COOLING & HEATING 12 mbh 230/208 v POWER AIRE "));
         rowData.add(5,item);
         item = new Hashtable();
         item.put(new Long(0),new String("Features:"));
         item.put(new Long(1),new String("SYSTEM COOLING & HEATING 12 mbh 230/208 v POWER AIRE SYSTEM1234 COOLING & HEATING 12 mbh 230/208 v POWER AIRE "));
         rowData.add(6,item);
         /*item.put(new Long(0),new String("Family Sequence"));
         item.put(new Long(1),new String("8.00"));
         rowData.add(5,item);
         item.put(new Long(0),new String("Family Sequence"));
         item.put(new Long(1),new String("8.00"));
         rowData.add(6,item);
         item.put(new Long(0),new String("Family Sequence"));
         item.put(new Long(1),new String("8.00"));
         rowData.add(7,item);
         return rowData;
    public String[] getColData()
         String[] colData = new String[]{"Attribute","Value"};
         return colData;
    public ArrayList getRowData1()throws MalformedURLException{
         ArrayList rowData = new ArrayList();
         Hashtable item = new Hashtable();
         String str = new String("http://biis:8080/assets/PRIMPRIM/Adj_BeacM_Small.jpg");
         URL url = new URL(str);
         ImageIcon ic = new ImageIcon(url);
         ImageIcon scaledImage = new ImageIcon(ic.getImage().getScaledInstance(getImageHeight(), -1,Image.SCALE_SMOOTH));
         item.put(new Long(0), scaledImage);
         rowData.add(0,item);
         String str1 = new String("http://biis:8080/assets/PRIMPRIM/Adj_BeacM_Small.jpg");
         URL url1 = new URL(str1);
         ImageIcon ic1 = new ImageIcon(url1);
         ImageIcon scaledImage1 = new ImageIcon(ic1.getImage().getScaledInstance(120, -1,Image.SCALE_DEFAULT));
         item.put(new Long(0),scaledImage1);
         rowData.add(1,item);
         return rowData;
    public String[] getColumns1(){
         String[] colData = new String[]{"Image"}; 
         return colData;
    public int getImageHeight(){
         ImageIcon ic = new ImageIcon("c:\\image\\ImageNotFound.gif");
         return ic.getIconHeight();
    class TextAreaCellRenderer extends JTextArea implements TableCellRenderer
         public TextAreaCellRenderer() {
              setEditable(false);
              setLineWrap(true);
              setWrapStyleWord(true);
         public Component getTableCellRendererComponent(JTable table,
              Object value, boolean isSelected, boolean hasFocus,
              int nRow, int nCol)
              if (value instanceof String)
                   setText((String)value);
              // Adjust row's height
              int width = table.getColumnModel().getColumn(nCol).getWidth();
              setSize(width, 1000);
              int rowHeight = getPreferredSize().height;
              if (table.getRowHeight(nRow) != rowHeight)
                   table.setRowHeight(nRow, rowHeight);
              this.setBackground(Color.WHITE);
              return this;

    I think Problem is between these code only
    for(int k=0;k<columnCount;k++)
                   TableCellRenderer renderer = null;
                   TableCellEditor editor = null;
                   renderer = new TextAreaCellRenderer();
                                                                itemTable.getColumnModel().getColumn(k).setCellRenderer(renderer);or in this renderer
    class TextAreaCellRenderer extends JTextArea implements TableCellRenderer
         public TextAreaCellRenderer() {
              setEditable(false);
              setLineWrap(true);
              setWrapStyleWord(true);
         public Component getTableCellRendererComponent(JTable table,
              Object value, boolean isSelected, boolean hasFocus,
              int nRow, int nCol)
              if (value instanceof String)
                   setText((String)value);
              // Adjust row's height
              int width = table.getColumnModel().getColumn(nCol).getWidth();
              setSize(width, 1000);
              int rowHeight = getPreferredSize().height;
              if (table.getRowHeight(nRow) != rowHeight)
                   table.setRowHeight(nRow, rowHeight);
              this.setBackground(Color.WHITE);
              return this;
    }

  • Selection of Custom JTable cell renderer inconsistenent between LAFs

    Sorry if that seems cryptic, but I don't know if I've run into a bug or not. I've recently switched from windows to linux and have noticed a problem with one of my programs. I have a "multiline" renderer that I made for my JTable. The renderer isn't terribly elegant, but when I'd select the row of the table, I made the multi-line renderer change its colors in response to the selection.
    This color selection switching works fine under the Metal LAF and the Windows LAF. However, this no longer works in the default look and feel is for linux (GTK+???). My multiline renderer in the JTable won't change its foreground/background in response to selection, but will if I use the Metal LAF under linux.
    Any idea what I'm doing wrong? Is this a bug? (I'm fairly certain I'm doing something silly, I just can't see it for the life of me).
    Here's the code I use to update the selection:
    class MultilineRenderer extends JTextArea
            implements TableCellRenderer {
        public MultilineRenderer(){
            super();
            setWrapStyleWord(false);
            setLineWrap(true);
            setFont(Const.TABLE_FONT);
            setOpaque(true);
        public Component getTableCellRendererComponent(
                JTable table, Object text,
                boolean isSelected, boolean hasFocus,
                int row, int column) {
            String data = (String)text;
            setText(data);
            if (isSelected){
                setForeground(table.getSelectionForeground());;
                setBackground(table.getSelectionBackground());
            } else {
                setForeground(table.getForeground());
                setBackground(table.getBackground());
            return this;
    }

    Some look and feels will ignore calls to setBackground and setForeground, and will instead decide their own colour.
    To quote the API documentation:
    "The background color affects each component differently and the parts of the component that are affected by the background color may differ between operating systems."
    I would imagine that this is your problem. Annoying, I know!

  • JTable Custom Renderer not working after sort

    Hi All,
    I have a JTable which has a default renderer. The point of the renderer is to color the background based on the second column.
    It all words fine, until I sort by any of the columns. Clicking on a column header sorts, but the original background color remains.
    The JTable was created with a class that extended DefaultTableModel.
    Any help or ideas would be appreciated.
    Thanks.
    table.setDefaultRenderer(Object.class, new MyColorCellRenderer());
    public class MyColorCellRenderer extends javax.swing.table.DefaultTableCellRenderer {
            public MyColorCellRenderer() {
                setForeground(Color.white);
                setOpaque(true);           
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {                   
                Component comp = super.getTableCellRendererComponent(
                         table,  value, isSelected, hasFocus, row, column);
                String s = table.getModel().getValueAt(row, 1).toString();
                if (s.equalsIgnoreCase("Man")) {
                    comp.setBackground(Color.red);
                } else if (s.equalsIgnoreCase("Woman")) {
                    comp.setBackground(Color.orange);
                } else if (s.equalsIgnoreCase("Child")) {
                    comp.setBackground(Color.lightGray);
                } else if (s.equalsIgnoreCase("Pet")) {
                    comp.setBackground(Color.darkGray);
                } else {
                    comp.setForeground(null);
                return (comp);
        }Edited by: PeterG on Sep 23, 2008 7:54 AM

    Absolutely correct and fantastic!
    Thank you very much.
    New code below.
    public class MyColorCellRenderer extends javax.swing.table.DefaultTableCellRenderer {
            private JTable m_Table;
            public MyColorCellRenderer(JTable table) {
                m_Table = table;
                setForeground(Color.white);
                setOpaque(true);           
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {                   
                Component comp = super.getTableCellRendererComponent(
                         table,  value, isSelected, hasFocus, row, column);
                String s = table.getModel().getValueAt(m_Table.convertRowIndexToModel(row), 1).toString();
                if (s.equalsIgnoreCase("Man")) {
                    comp.setBackground(Color.red);
                } else if (s.equalsIgnoreCase("Woman")) {
                    comp.setBackground(Color.orange);
                } else if (s.equalsIgnoreCase("Child")) {
                    comp.setBackground(Color.lightGray);
                } else if (s.equalsIgnoreCase("Pet")) {
                    comp.setBackground(Color.darkGray);
                } else {
                    comp.setForeground(null);
                return (comp);
    }

  • JTable JCombo renderer ignores setForeground

    The setForeground calls in the renderer are ignored. The JCombo values are displayed in JTable foreground color. Any fix for this?
    Thanks
    class ComboCellRenderer extends DefaultTableCellRenderer implements TableCellRen
    derer
      protected static Border m_noFocusBorder    =    new
      EmptyBorder (1,                1,              1,              1);
      protected static    Border    m_focusBorder =
      UIManager.getBorder("Table.focusCellHighlightBorder");
      public
      ComboCellRenderer
      public Component
      getTableCellRendererComponent
      (JTable table,hasFocus,
       int nRow, int nCol)
        Color fg=new Color(255,0,0);
        //ColorData cvalue = new ColorData(value);
        if (table.getModel().getValueAt(nRow, 11).toString().trim().equals("Lucent")
          setForeground(fg);
        else if (table.getModel().getValueAt(nRow, 11).toString().trim().equals("Nor
    tel"))
          setForeground(Color.blue);
        else
          setForeground(Color.green);
        setBackground
          (isSelected && !hasFocus ?         table.getSelectionBackground() : table.
    getBackground ());
        //setForeground (isSelected && !hasFocus ?
        //   table.getSelectionForeground() : table.getForeground ());
        setFont (table.getFont ());
        //setBorder (hasFocus ? m_focusBorder : m_noFocusBorder);
        int rowHeight =     getPreferredSize().height; return this;
      public String getToolTipText (MouseEvent event)
        return null;
    } //class ComboCellRendererif (table.getRowHeight(nRow) < rowHeight)
    table.setRowHeight (nRow, rowHeight);
    Object value,
    boolean
    isSelected,
    boolean

    OOPS...
    It seems that through a cut-and-paste error, I lost the first few lines of my code in the previous post. Here it is in its entirety for anyone who is interested...
    class CheckBoxTableCellRenderer extends JCheckBox implements TableCellRenderer {
      Border noFocusBorder;
      Border focusBorder;
      public CheckBoxTableCellRenderer() {
        super();
        setContentAreaFilled(true);  // use this instead of setOpaque()
        setBorderPainted(true);
        setHorizontalAlignment(SwingConstants.CENTER);
        setVerticalAlignment(SwingConstants.CENTER);
      public Component getTableCellRendererComponent(JTable table, Object value,
                                                     boolean isSelected,
                                                     boolean hasFocus,
                                                     int row, int column) {
        if(table == null) {
        else {
          if (isSelected) {
            setForeground(table.getSelectionForeground());
            setBackground(table.getSelectionBackground());
          else {
            setForeground(table.getForeground());
            setBackground(table.getBackground());
          setEnabled(table.isEnabled());
          setComponentOrientation(table.getComponentOrientation());
          if (hasFocus) {
            if (focusBorder == null) {
              focusBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
            setBorder(focusBorder);
          else {
            if (noFocusBorder == null) {
              if (focusBorder == null) {
                focusBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
              if (focusBorder != null) {
                Insets n = focusBorder.getBorderInsets(this);
                noFocusBorder = new EmptyBorder(n);
            setBorder(noFocusBorder);
          setSelected(Boolean.TRUE.equals(value));
        return this;
    }

  • Icons in jtable - custom rendering

    The following code creates a table, then places an exclaimation point in each column in which the value exceeds the treshold value. I would like to modify the code so that, it places the exclaimation point in the status column of the row containing the value exceeding the treshold.
    I need some assistance please.
    import java.awt.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.table.*;
    public class TableRenderer extends JFrame
    JTable table;
    double T = 1;
    public TableRenderer()
    String[] columnNames = {"Status","Date", "Integer", "String"};
    Object[][] data =
    {"",new Date(), new Integer(1), "A"},
    {"",new Date(), new Integer(2), "B"},
    {"",new Date(), new Integer(3), "C"},
    {"",new Date(), new Integer(4), "D"}
    DefaultTableModel model = new DefaultTableModel(data, columnNames);
    table = new JTable( model )
    public Class XXXgetColumnClass(int column)
    return getValueAt(0, column).getClass();
    JScrollPane scrollPane = new JScrollPane( table );
    getContentPane().add( scrollPane );
    // Create cell renderer
    TableCellRenderer renderer = new TestRenderer(T);
    table.setDefaultRenderer(Object.class, renderer);
    //table.setDefaultRenderer(Number.class, renderer);
    //table.setDefaultRenderer(Date.class, renderer);
    public static void main(String[] args)
    TableRenderer frame = new TableRenderer();
    frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
    frame.pack();
    frame.setVisible(true);
    import java.awt.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.table.*;
    class TestRenderer extends DefaultTableCellRenderer
        double Threshold;
            public TestRenderer(double t) {
                Threshold = t;
            public Component getTableCellRendererComponent(
            JTable table,
            Object value,
            boolean isSelected,
            boolean hasFocus,
            int row,
            int column)
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            setOpaque( true );
            Icon bang = new ImageIcon("C:/j2sdk1.4.2_04/bin/bang.gif");
                    if (value instanceof Number){
                            if (((Number)value).doubleValue() > Threshold){
                                setIcon(bang);
                            else{
                                setIcon(null);
                                setBackground(Color.red);
                    else{
                                setIcon(null);
                                setBackground(Color.yellow);                           
            return this;

    I would like to modify the code so that, it places the exclaimation point in the status column of the row containing the value exceeding the treshold.So you add the renderer to the first column, not the column containing the Integer. Now in the renderer you need to get the value directly from the model:
    Object testValue = table.getModel().getValueAt(row, 2);
    if (testValue instanceof Number)

  • Which decide the JTable cell renderer behavior

    Hi,
    I have a subclass of JTable in which I overwrite the JTable.valueChanged() function ( which is used to implement the ListSelectionListener)
    I have called setCellSelectionEnabled(true); to enable only the cell selection
    I find if I don't call super.valueChanged() in myTable. valueChanged() method, the table rendering is in correct. For example,
    first I select cell at row=2, col=3 (2, 3),
    the cell get rendered.
    then I select cell (0,3).
    I find no any cell get rerendered.
    but I hope this time the previous selected cell and the new selected cell are re-rendered.
    This problem only happens on the same column.
    If I first select cell (2,3) then select cell (2,5), then both of these cell get rerendered as I want.
    However, If I call super.valueChanged(), all the cell re-render works fine.
    I can see in the JTable.valueChanged(), it has varibles as:
    lastSelectedRow, lastSelectedCol, but I don't find them used in any tableCellRenderer.
    I wonder where in the JTable code or any related code it call the table cell renderer when cell selection changed?
    Thanks

    I overwrite the JTable.valueChanged() function ( which is used to implement the ListSelectionListener)I would think you should use the getSelectionModel() method and then add a ListSelectionListener to the selection model.
    If you need further help then you need to create a "Short, Self Contained, Compilable and Executable, Example Program (SSCCE)",
    see http://homepage1.nifty.com/algafield/sscce.html,
    that demonstrates the incorrect behaviour, because I can't guess exactly what you are doing based on the information provided.
    Don't forget to use the "Code Formatting Tags",
    see http://forum.java.sun.com/help.jspa?sec=formatting,
    so the posted code retains its original formatting.

  • JTable custom renderer never calls getTableCellRendererComponent()

    I have a custom renderer for Dates in my JTable. I've set it as the renderer on Date columns and I've also tried setting it as the table default for the Date type. In both cases the getTableCellRendererComponent() method never gets called.
    I've also tried right-justifying String columns with
              DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)table.getDefaultRenderer(String.class);
              renderer.setHorizontalAlignment(JLabel.RIGHT);
    but the Strings are always left-justified. Same with integers.
    I verify that the new renderer / alignments are actually set immediately after setting them. A few method calls later I notice that the alignments have changed back. My custom date renderer is still set, however.
    My code calls fireTableStructureChanged(). I set/reset all renderers after the call to fireTableStructureChanged(). I wonder if fireTableStructureChanged() rebuilds the table some teim later wiping out the renderer / alignments that I've set and replacing them with the defaults.
    Is there a callback or some method that I need to override after calling fireTableStructureChanged() in order to get my renderer / alignments to remain in effect?

    I can't post the code because it is proprietary and the application itself is large.
    The trouble seems to start when I call fireTableStructureChanged(). None of the toy examples in books that I've seen address fireTableStructureChanged(). The JavaDocs for Swing don't tell you about all of the side effects of fireTableSTructureChanged().
    You're comment about overriding getColumnClass() got my custom data renderer working. The Javadocs for DefaultTableModel and JTable don't mention when you need to override getColumnClass(). Overriding getColumnClass() in the TableModel seems to apply to JTable as well. I don't understand why, but it seems to work.
    I am able to justify my columns be creating a default renderer and calling setHorizontalAlignment() on it and setting it as the default for the JTable. The code below doesn't work, however:
    DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)table.getDefaultRenderer(int.class);
    renderer.setHorizontalAlignment(JLabel.RIGHT);
    It seems that the default renderers reset themselves back to their default state. I have no idea why, but that is what I am seeing.
    There is also a big difference in the way that primitives and wrappers are handled (i.e. int compared to Integer).
    One of the other posters here said that if I call setModel() that I would have to reset the renderers. The Javadocs don't say anything about that. (I only call setModel during initialization. I do update the actual data in the TableModel which can change the structure of the table. That is when I call fireTableStructureChanged() and all the difficulties start.)
    This whole episode has shown that the Swing Javadocs are next-to-worthless for writing real-world Swing applications. I've written several Swing applications over the years, and once they get beyond the simple level they become difficult to write and maintain due to the lack of documentation. For my next Java GUI I'm going to check out JavaFX (as soon as it is available on Linux). I don't see how it could be worse than Swing.
    Thanks for all of your help. You got me on the path to getting this solved.

  • Jtable custom renderer

    how to set or create custom renderer for a Jtable ?.. i want have following components in each cell of jtable.
    1)checkbox
    2)icon
    3)combobox
    i know how to render these components for Jtree, but i didn't get any method like setCellRendere() for Jtable.
    plz help !!

    You can use the both:
    JTable method:
    +Sets a default cell renderer to be used if no renderer has been set in a TableColumn.+
    public void setDefaultRenderer(Class<?> columnClass, TableCellRenderer renderer)TableColumn method:
    +Sets the TableCellRenderer used by JTable to draw individual values for this column.+
    public void setCellRenderer(TableCellRenderer cellRenderer)

  • Disabling the border on JTable cell renderer

    Hello all
    I've developed a JTable that doesn't allow cell editing and only allows single-row selection. It works fine, I've allowed the user to press <tab> to select the next row or click the mouse to select any row. The row selected is high-lighted and I'm happy with how it works.
    However:
    Due to the single-row selection policy, it doesn't make sense to display a border around any cell that has been clicked. I would therefore like to prevent the JTable from displaying a border on any cell the user has clicked.
    I've checked out the API documentation for JTable and the closest I've been able to get is to construct a DefaultTableCellRenderer and then use JTable.setDefaultRenderer. The problem is I don't know how to set the DefaultTableCellRenderer to NOT display a border when selected.
    I can see a method called getTableCellRendererComponent which takes parameters that seemingly return a rendering component, but should I specify isSelected = true and isFocus = true? And what should I do once I have the Component? I've tried casting it to a JLabel and setBorder(null) on it, but the behaviour of the table remains the same.
    I've tried all sorts of things but to no avail. I'm finding it all a bit confusing...
    Why oh why isn't there simply a setTableCellRendererComponent()? ;)

    JTable can potentially use multiple renderers based on the type of data in each column, so you would need to create multiple custom renderers using the above approach. The following should work without creating custom renderers:
    table = new JTable( ... )
         public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
              Component c = super.prepareRenderer(renderer, row, column);
              ((JComponent)c).setBorder(null);
              return c;
    };

  • JTable  and Renderer

    Hello guru,
    I have a JTable in my application and i have defined a renderer for the first column of my
    JTable.
    This is the code for this renderer
    public class LabelRenderer extends JLabel implements TableCellRenderer
    public Component getTableCellRendererComponent(JTable table, Object value,
    boolean isSelected, boolean hasFocus, int row, int column)
    return this;
    I will like to change the background color of the first column and only in the active row of my JTable or ideally set a picture in this column. is this possible?
    I think i have to write something in this event:
    table.getModel().addTableModelListener(new TableModelListener()
    public void tableChanged(TableModelEvent e)
    int row = e.getFirstRow();
    int column = e.getColumn();
    //something .......
    How can i do this ?
    thank you for your help

    Just to add onto that:
    1) the method call is setBackground(Color c). not setBackgroundColor.
    2) and you'll have to call setOpaque(true) also or the color won't show up. You can do this in your constructor.
    Here is some example code to do what you wan. The unimplemented methods at the end should be included in your renderer class. It speeds up renderering a lot. See the java api docs for the reasons if you are curious:
    public class DataRenderer extends JLabel implements TableCellRenderer {
    private Color selectionColor;
    private Color backColor;
    public DataRenderer () {
              setOpaque(true);
              setHorizontalAlignment(SwingConstants.RIGHT);     
              selectionColor=new Color(206,207,255);
              backColor = new Color(240,240,240);     
    public Component getTableCellRendererComponent(
    JTable table, Object value,
    boolean isSelected, boolean hasFocus,
    int row, int col) {
              if (value==null) //it hasn't been set yet               
                   return null;     
         if(isSelected)
         setBackground(selectionColor);
         else
         setBackground(backColor);
         setText(value.toString());
    return this;
         public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue){
         protected void firePropertyChange(String propertyName, Object oldValue, Object newValue){
         public void repaint(long tm, int x, int y, int width, int height){
         public void repaint(Rectangle r){
         public void revalidate(){
         public void validate() {
    Good Luck!

  • JTable only renders cells visible in viewport

    I have a JTable which is in a JScrollPane. The JTable has multi-row spanning cells. Consider a cell 0,0 that spans 4 rows. I scroll the table so that rows 0 thru 2 are not visible. I then replace the model with a new model containing new data. The table, with it's new model, is rendered for the Viewport that is visible and the scrollpane remains scrolled where I left it. Which is what I want. But since I have multi-row spaning cells the cells outside the viewport are not considered for rendering. Since cell 0,0 spans 4 rows, cell 0.3 (which is really part of cell 0,0) does not appear rendered correctly.
    How do I get all cells of the table to render (albiet I wouldn't see them unless they span into the viewport) instead of just those in the viewport.
    I need something like JTable.considerViewportExtentsWhenRendering(true);

    You will need to override the paint method of the BasicTableUI to do what you wanted. It's a bit tricky but doable.
    ;o)
    V.V.

Maybe you are looking for