Forum Stats

  • 3,728,034 Users
  • 2,245,522 Discussions
  • 7,853,255 Comments

Discussions

How to insert a JComponent into a cell of JTable

819715
819715 Member Posts: 11
edited February 2011 in Swing
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

Answers

  • StanislavL
    StanislavL Member Posts: 309
    Take a look at TableCellEditor/TableCellRenderer.
  • 819715
    819715 Member Posts: 11
    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.
  • sabre150
    sabre150 Member Posts: 1,405
    As has already been said - take a look at TableCellEditor/TableCellRenderer.
  • Jörg
    Jörg Member Posts: 1,301
    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"
  • 819715
    819715 Member Posts: 11
    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
  • mKorbel
    mKorbel Member Posts: 306
    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
  • 819715
    819715 Member Posts: 11
    edited December 2010
    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
  • 800346
    800346 Member Posts: 1,094
    edited January 2011
    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
  • 819715
    819715 Member Posts: 11
    edited January 2011
    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
  • darrylburke
    darrylburke Member Posts: 18,007
    >
    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
  • kleopatra-JavaNet
    kleopatra-JavaNet Member Posts: 1,105 Gold Badge
    edited January 2011
    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
  • kleopatra-JavaNet
    kleopatra-JavaNet Member Posts: 1,105 Gold Badge
    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();
            }
        }
    
    }
  • 800346
    800346 Member Posts: 1,094
    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é
  • kleopatra-JavaNet
    kleopatra-JavaNet Member Posts: 1,105 Gold Badge
    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
  • 800346
    800346 Member Posts: 1,094
    edited January 2011
    Kleopatra wrote:
    Calling updateUI in application code is wrong whatever they did or didn't <g>
    Don't mean any specific method.The wrong JSlider behaviour in the above context is an example of what I mean.

    Cheers,
    André
  • 819715
    819715 Member Posts: 11
    thanks for give me support and i learning alot with this form
This discussion has been closed.