1 2 Previous Next 16 Replies Latest reply on Feb 7, 2011 3:33 PM by 819715

    How to insert a JComponent into a cell of JTable

    819715
      Hi,

      I am facing one problem. I need to place the JTextField/JComboBox/JTable into a cell of JTable.
      I need the solution for following senario,

      The JTextField/JComboBox/JTable into a cell of JTable because the values are filling for these 3 components are using some other operations. finally I should place all these 3 components in to a JTable like

      Column1 -> JTextField
      Column2 -> JComboBox
      Column3 -> JTable

      Edited by: 816712 on Dec 29, 2010 4:07 AM
        • 1. Re: How to insert a JComponent into a cell of JTable
          StanislavL
          Take a look at TableCellEditor/TableCellRenderer.
          • 2. Re: How to insert a JComponent into a cell of JTable
            819715
            Sorry for Trouble,

            If I need to set the JComponent(JTextField/JTable/JComboBox) irrespective of the columns, I mean If need to set a JComponent in to a Cell (like 3row of 2nd Column) and the JTable has the capacity of 3rows and 3 columns.
            • 3. Re: How to insert a JComponent into a cell of JTable
              sabre150
              As has already been said - take a look at TableCellEditor/TableCellRenderer.
              • 4. Re: How to insert a JComponent into a cell of JTable
                Jörg
                Do you know the tutorial? If not, have a look at http://download.oracle.com/javase/tutorial/uiswing/components/table.html#editrender
                and the example further down "Using a Combo Box as an Editor"
                • 5. Re: How to insert a JComponent into a cell of JTable
                  819715
                  Hi,

                  If I use TableCellEditor the cell was updating when I click the Cell of the Table. but I need to update at the time of loading only.

                  I worte like this

                  "

                  public class myCellEditor extends AbstractCellEditor implements TableCellEditor {
                  JComponent jObject;
                  JPanel jPanel;

                  public Object getCellEditorValue() {

                  jPanel = new JPanel();

                  jPanel.add(jObject);

                  return jPanel;
                  }

                  public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row,
                  int column) {
                  jObject = < here I can get the Table from other Source>
                  return jObject;
                  }
                  } "

                  please do any favor for this
                  • 6. Re: How to insert a JComponent into a cell of JTable
                    mKorbel
                    please check these articles on

                    http://www.java2s.com/Code/Java/Swing-JFC/Table.htm

                    http://www.java2s.com/Code/Java/Swing-JFC/CreatingaCustomTableCellEditorinaJTableComponent.htm

                    http://www.java2s.com/Tutorial/Java/0240__Swing/EditingTableCellsJComboBoxAsTableCellRenderer.htm

                    much luck with that and happy new year
                    • 7. Re: How to insert a JComponent into a cell of JTable
                      819715
                      How to resize the Component( which one inserted into a cell of JTable) width to Cell Width in JTable

                      Edited by: 816712 on Dec 31, 2010 6:07 AM
                      • 8. Re: How to insert a JComponent into a cell of JTable
                        800346
                        816712 wrote:
                        How to resize the Component( which one inserted into a cell of JTable) width to Cell Width in JTable
                        Simple question, but hard to answer for me. The component seems to resize only when its cell gains focus or loses focus.

                        I thought about adding a ColumnModelListener to the ColumnModel. In columnMarginChanged I tried to repaint the table. This didn't have any effect. I'm afraid there is no simple solution.

                        Cheers,
                        André

                        EDIT: I tried with JSlider. Other components seem to resize automatically.
                        EDIT2: I inserted "rendererComponent.updateUI();" into the renderer, which solved the problem.
                        public class TableWithSliderDemo extends JFrame {
                            JTable table;
                            public TableWithSliderDemo() {
                                table = new JTable(3, 3);
                                table.setValueAt(new JSlider(), 2, 1);
                                table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
                                    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                                        if (value instanceof JComponent) {
                                            ((JComponent) value).updateUI();//<-------------------
                                            return (JComponent) value;
                                        } else {
                                            return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                                        }
                                    }
                                });
                                add(new JScrollPane(table));
                                pack();
                            }
                            public static void main(final String args[]) {
                                SwingUtilities.invokeLater(new Runnable() {
                                    public void run() {
                                        new TableWithSliderDemo().setVisible(true);
                                    }
                                });
                            }
                        }
                        Edited by: Andre_Uhres on 01.01.2011 21:12

                        Edited by: Andre_Uhres on 02.01.2011 08:52

                        Edited by: Andre_Uhres on 02.01.2011 09:10 sample code
                        • 9. Re: How to insert a JComponent into a cell of JTable
                          819715
                          I created Custom TableCellRenderer class and used as follows

                          Table Class:
                          *...*
                          *...*

                          JTable compareTable= new JTable(<CustomModelClass>);       //Setting the Data using Custom Model class

                          for(int i=1 ; i< compareTable.getColumnCount();i++)
                          *{*
                          int width=0;
                          int height=0;
                          TableColumn tc = compareTable.getColumnModel().getColumn(i);


                          tc.setCellRenderer(new myCellRenderer(<CustomModelClass>));
                          *}*
                          compareTable.getTableHeader().setReorderingAllowed(false);
                          compareTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                          compareTable.setFont(new Font("Helv", Font.PLAIN, 12));
                          compareTable.setRowHeight(21);
                          compareTable.revalidate();


                          JScrollPane jsp = new JScrollPane(compareTable);

                          *...*

                          Custom CellRenderer

                          *public class myCellRenderer implements TableCellRenderer {*

                          MyTableModel mtm;
                          Object Value;


                          boolean flag = false;

                          *public myCellRenderer(MyTableModel mtm) {*
                          this.mtm = mtm;

                          *}*

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

                          int height =0 ;
                          JPanel jPanel = new JPanel();
                          JTextField nullText = new JTextField();
                          nullText.setText("N/A");
                          JComponent jObject;        //JComponent value may be JComboBox, JTextField, JTable

                          *try{*

                          jObject = setCell(column, row,table);       // I can get the JComponent Value

                          if(jObject != null)
                          *{*
                          *if (jObject instanceof JComponent) {*
                          *( (JComponent) jObject).updateUI();*
                          return (JComponent) jObject;
                          *}*
                          *}*

                          return nullText;
                          *}*
                          catch(Exception e)
                          *{*
                          jObject = nullText;
                          *}*
                          jPanel.add(jObject);
                          return jPanel;

                          *}*

                          public JComponent setCell(int column,int row,JTable table)
                          *{*

                          *// JComponent Code*

                          return JComponent; *}*
                          *}*


                          my question was If I try to run the Program, the Program continuously iterating the myCellRenderer class, it's consuming CPU time more than 50% usage, how can I reduce the time consuming process. I need to place the JComponent Values in to the cell of JTable.

                          and Also I observed when ever I insert JTable then the
                          getTableCellRendererComponent(JTable table, Object value,boolean isSelected,boolean hasFocus, int row,int column) method was iterating n' number of times(it's in a loop) until unless I closed the window(JFrame)

                          Edited by: 816712 on Jan 7, 2011 2:27 AM

                          Edited by: 816712 on Jan 7, 2011 2:34 AM
                          • 10. Re: How to insert a JComponent into a cell of JTable
                            darrylburke
                            >
                            Moderator advice: Please read the announcement(s) at the top of the forum listings and the FAQ linked from every page. They are there for a purpose.

                            Then edit your post and format the code correctly.

                            db
                            • 11. Re: How to insert a JComponent into a cell of JTable
                              kleopatra-JavaNet
                              Andre_Uhres wrote:
                              EDIT2: I inserted "rendererComponent.updateUI();" into the renderer, which solved the problem.
                              Andre, you are probably not overly astonished that I strongly disagree <g>. It's a clear no-go: whatever the problem, updateUI is never a solution - it's a sledgehammer hack which smoothes out the real reason with tons of dust with occasionally devastating side-effects ;-) When seemingly needed to make something "work" there's deeper trouble somewhere, options are:

                              - in custom code
                              - in core code

                              Thanks to the nice clean example, the first is clearly excluded. Which leaves the latter to dig into. Culprit is quickly found (and that's the only benefit of trying out updateUI - if re-installing the ui-delegate helps, that fact hints to the origin of the problem): it's BasicSliderUI with its crazily excessive size state caching. That cached state is never updated when the slider is used as a rendering component, even though the ui tries to get notified: it installs a ComponentListener and re-calculates the sizes on componentResized. Unfortunately, that's not good enough - ComponentListeners are not notified when the resizing happens in the CellRendererPane's paintComponent (still don't understand why not: couldn't verify my initial guess that the event posted to the eventQueue isn't propagated to the listeners because at the time of processing the queue the component is not part of the hierarchy. Which in fact it still may be, if the ui doesn't remove it from the rendererPane. Or might be related to the rendererPane "move it out of scope" by resizing to zero ... no idea, comments welcome :)

                              What I could verify, though, is that forcing the notification helps, as shown by adding the following lines to the example:
                                      JSlider slider = new JSlider() {
                              
                                          /** 
                                           * @inherited <p>
                                           */
                                          @Override
                                          public void reshape(int x, int y, int w, int h) {
                                              super.reshape(x, y, w, h);
                                              if (getParent() instanceof CellRendererPane) {
                                                  // force sending of componentResized
                                                  ComponentEvent e = new ComponentEvent(this,
                                                          ComponentEvent.COMPONENT_RESIZED);
                                                  processComponentEvent(e);                
                                              }
                                          }
                                          
                                      };
                                      
                                      ComponentListener l = new ComponentAdapter() {
                              
                                          /** 
                                           * @inherited <p>
                                           */
                                          @Override
                                          public void componentResized(ComponentEvent e) {
                                              LOG.info("got resized:" + e);
                                          }
                              
                                      };
                                      slider.addComponentListener(l);
                              Frustratingly, the core SwingTeam at times isn't overly alert when reading bug reports: more than a lustrum ago (2005!) they got a report about a problem with using JSlider as a cellEditor

                              http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6348946

                              While that particular issue is finally fixed in 7 ( har har ), the example code also mentioned the seeming need for calling updateUI to make it "work" - and obviously nobody in the team stumbled across that goofer .. dooooohhh ...

                              Anyway, what a nice winter Sunday afternoon puzzler :-)

                              Cheers
                              Jeanette
                              • 12. Re: How to insert a JComponent into a cell of JTable
                                kleopatra-JavaNet
                                still don't understand what's going on - just experimental evidence:

                                - ComponentListeners are always notified for "normal" free-standing (that is: not added to the hierarchy) components on manual resizing/relocating
                                - ComponentListeners do get at least the "last" resized/moved when the component is added to a free-standing CellRendererPane (which wouldn't help in the ui-delegate, as that is the zero-width/height event)
                                - ComponentListeners get nothing if the CellRendererPane itself is added to the hierarchy

                                And the moral? ComponentListeners might not be good enough if the component is used as a rendering component (HierarchyListeners are). Or the other way round: uis which do lots of size caching must be carefully implemented to allow for painless usage of the comp as rendering component ...

                                Below is some code to play with (in terms of swingx test support .. too lazy to re-write)

                                Cheers
                                Jeanette
                                public class SliderExperiments extends InteractiveTestCase {
                                    
                                    public void interactiveComponentEvent() {
                                        final JComponent renderingComponent = new JLabel();
                                        renderingComponent.addComponentListener(createComponentListener());
                                        // simulate context in ui-delegate paint
                                        // need a target to render on
                                        final JComponent target = new JPanel();
                                        // and a CellRendererPane which is added to the target
                                        final CellRendererPane addedPane = new CellRendererPane();
                                        target.add(addedPane);
                                        
                                        JXFrame frame = wrapInFrame(target, "componentEvent"); 
                                        Action action = new AbstractAction("paintOnAddedRendererPane") {
                                            
                                            BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
                                            @Override
                                            public void actionPerformed(ActionEvent e) {
                                                Dimension dim = renderingComponent.getSize();
                                                Graphics g = image.createGraphics();
                                                addedPane.paintComponent(g, renderingComponent, target, 0, 0, dim.width + 20, dim.height + 20);
                                                addedPane.removeAll();
                                                g.dispose();
                                            }
                                        };
                                        addAction(frame, action);
                                        // compare to free-flying cellRendererPane
                                        final CellRendererPane freePane =  new CellRendererPane();
                                        Action paintFree = new AbstractAction("paintOnFreeRendererPane") {
                                            
                                            BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
                                            @Override
                                            public void actionPerformed(ActionEvent e) {
                                                Dimension dim = renderingComponent.getSize();
                                                Graphics g = image.createGraphics();
                                                addedPane.paintComponent(g, renderingComponent, target, 0, 0, dim.width + 20, dim.height + 20);
                                                freePane.removeAll();
                                                g.dispose();
                                            }
                                        };
                                        addAction(frame, paintFree);
                                        // compare to manual resizing of free-flying component
                                        final JComponent label = new JLabel();
                                        label.addComponentListener(createComponentListener());
                                        Action resize = new AbstractAction("resizeFreeComponent") {
                                            
                                            @Override
                                            public void actionPerformed(ActionEvent e) {
                                                Rectangle dim = label.getBounds();
                                                label.setBounds(dim.x + 2, dim.y + 2, dim.width + 20, dim.height + 20);
                                            }
                                        };
                                        addAction(frame, resize);
                                        show(frame);
                                    }
                                
                                    private ComponentListener createComponentListener() {
                                        ComponentListener l = new ComponentListener() {
                                
                                            /** 
                                             * @inherited <p>
                                             */
                                            @Override
                                            public void componentResized(ComponentEvent e) {
                                                LOG.info("" + e);
                                            }
                                
                                            @Override
                                            public void componentHidden(ComponentEvent e) {
                                                LOG.info("" + e);
                                            }
                                
                                            @Override
                                            public void componentMoved(ComponentEvent e) {
                                                LOG.info("" + e);
                                            }
                                
                                            @Override
                                            public void componentShown(ComponentEvent e) {
                                                LOG.info("" + e);
                                            }
                                            
                                            
                                        };
                                        return l;
                                    }
                                
                                    private HierarchyListener createHierarchyListener() {
                                        HierarchyListener h = new HierarchyListener() {
                                            
                                            @Override
                                            public void hierarchyChanged(HierarchyEvent e) {
                                                LOG.info("got hierarchy:" + e);
                                                
                                            }
                                        };
                                        return h;
                                    }
                                
                                    @SuppressWarnings("unused")
                                    private static final Logger LOG = Logger.getLogger(SliderExperiments.class
                                            .getName());
                                
                                    public static void main(String[] args) {
                                        SliderExperiments test = new SliderExperiments();
                                        try {
                                            test.runInteractiveTests();
                                        } catch (Exception e) {
                                            e.printStackTrace();
                                        }
                                    }
                                
                                }
                                • 13. Re: How to insert a JComponent into a cell of JTable
                                  800346
                                  Andre, you are probably not overly astonished that I strongly disagree
                                  At least I'm not more surprised about it than about the years of hesitation of the Swing team to make their classes more user friendly.

                                  Cheers,
                                  André
                                  • 14. Re: How to insert a JComponent into a cell of JTable
                                    kleopatra-JavaNet
                                    Andre_Uhres wrote:
                                    Andre, you are probably not overly astonished that I strongly disagree
                                    At least I'm not more surprised about it than about the years of hesitation of the Swing team to make their classes more user friendly.
                                    ... meaning is ..? Honestly don't understand what you are trying to say. The Swing team did or didn't whatever they did or didn't, rarely listening to developer feedback. Calling updateUI in application code is wront whatever they did or didn't <g>

                                    Cheers
                                    Jeanette
                                    1 2 Previous Next