1 2 Previous Next 15 Replies Latest reply on Jan 5, 2009 6:58 PM by darrylburke

    JButton inside JTable Cell

    800429
      Hi guys, I really need some help......

      I am working with JTable, and would like to show a JButton inside the last table column... This button will perform some actions when the user click on it.

      But I don't know how to solve some problems. I already create the table model, renderer, cell editor, my fired event are almos right, but I really think that are a lot to do until finish it.

      Right now, I am with the followign problems:
      1) How can I do to the button (inside the table) fire an event every time the user click on it, instead to force the user to click on button and press the enter?!!?!?

      2) I would like to made the button disappear after the user click on it (or force it do setEnabled(false) to prevent user repeat the same action. To solve it I set the CellEditor component to not visible when the stoppingEdit is finished, but whem the user click on another table row my old button becomes visible automaticaly. How can I fix this things?!!??

      ps: I know that it is a very complicated thing, and propably will need a lot of source code, so if anyone knows a good tutorial it will be welcome too.

      Thanks all
        • 1. Re: JButton inside JTable Cell
          800429
          Hi guys, I am here again!!!! I think a lot of about the problem commented before and fix somethings, but at each time I gotted some "bug problems"...

          Just to comment, every time I press a addButton I add a row into my model
          model.addRow(...)
          and when I press the clearButton I remove all rows from my table. But some times neither all rows are removed and the rows are not add at a logical order, sometimes the rows jump from 0 to 3, and the clear just remove some rows.

          I sure it is not a java languange bug, but I really are lost, because I don't find at any place how to understand how tables, models, renderer, editors, and anything else worlks....

          Please help. Thanks
          • 2. Re: JButton inside JTable Cell
            camickr
            But some times neither all rows are removed
            Use DefaultTableModel.setRowCount(0);
            2) I would like to made the button disappear after the user click on it (or
            force it do setEnabled(false) to prevent user repeat the same action.
            From my example below you could set the value of the cell to "". Then you could override the isCellEditable() method to return false when the "button cell" contains "".

            Here is some example code I've been playing with that may (or may not) give you some ideas:
            import java.awt.*;
            import java.awt.event.*;
            import java.util.*;
            import javax.swing.*;
            import javax.swing.table.*;
            
            public class TableButton3 extends JFrame
            {
                public TableButton3()
                {
                    String[] columnNames = {"Date", "String", "Integer", "Decimal", ""};
                    Object[][] data =
                    {
                        {new Date(), "A", new Integer(1), new Double(5.1), "Delete0"},
                        {new Date(), "B", new Integer(2), new Double(6.2), "Delete1"},
                        {new Date(), "C", new Integer(3), new Double(7.3), "Delete2"},
                        {new Date(), "D", new Integer(4), new Double(8.4), "Delete3"}
                    };
            
                    DefaultTableModel model = new DefaultTableModel(data, columnNames);
                    JTable table = new JTable( model )
                    {
                        //  Returning the Class of each column will allow different
                        //  renderers to be used based on Class
                        public Class getColumnClass(int column)
                        {
                            return getValueAt(0, column).getClass();
                        }
                    };
            
                    JScrollPane scrollPane = new JScrollPane( table );
                    getContentPane().add( scrollPane );
            
                    //  Create button column
                    ButtonColumn buttonColumn = new ButtonColumn(table, 4);
                }
            
                public static void main(String[] args)
                {
                    TableButton3 frame = new TableButton3();
                    frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
                    frame.pack();
                    frame.setVisible(true);
                }
            
                class ButtonColumn extends AbstractCellEditor
                    implements TableCellRenderer, TableCellEditor, ActionListener
                {
                    JTable table;
                    JButton renderButton;
                    JButton editButton;
                    String text;
            
                    public ButtonColumn(JTable table, int column)
                    {
                        super();
                        this.table = table;
                        renderButton = new JButton();
            
                        editButton = new JButton();
                        editButton.setFocusPainted( false );
                        editButton.addActionListener( this );
            
                        TableColumnModel columnModel = table.getColumnModel();
                        columnModel.getColumn(column).setCellRenderer( this );
                        columnModel.getColumn(column).setCellEditor( this );
                    }
            
                    public Component getTableCellRendererComponent(
                        JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
                    {
                        if (hasFocus)
                        {
                            renderButton.setForeground(table.getForeground());
                            renderButton.setBackground(UIManager.getColor("Button.background"));
                        }
                        else if (isSelected)
                        {
                            renderButton.setForeground(table.getSelectionForeground());
                             renderButton.setBackground(table.getSelectionBackground());
                        }
                        else
                        {
                            renderButton.setForeground(table.getForeground());
                            renderButton.setBackground(UIManager.getColor("Button.background"));
                        }
            
                        renderButton.setText( (value == null) ? "" : value.toString() );
                        return renderButton;
                    }
            
                    public Component getTableCellEditorComponent(
                        JTable table, Object value, boolean isSelected, int row, int column)
                    {
                        text = (value == null) ? "" : value.toString();
                        editButton.setText( text );
                        return editButton;
                    }
            
                    public Object getCellEditorValue()
                    {
                        return text;
                    }
            
                    public void actionPerformed(ActionEvent e)
                    {
                        fireEditingStopped();
                        System.out.println( e.getActionCommand() + " : " + table.getSelectedRow());
                    }
                }
            }
            • 3. Re: JButton inside JTable Cell
              800429
              Very thanks, Just to report another interested users, my big mistake was only implements the interfaces editor and renderer and don't extends any abstract model......

              So without a default implementation I implement all method by myself and they had bugs.

              Thanks.
              • 4. Re: JButton inside JTable Cell
                843805
                I want to hide the buttons, so I used setVisible(false);
                This doesn't worked out, could anyone help me?
                • 5. Re: JButton inside JTable Cell
                  843805
                  did you try to refresh the JTable or to repaint the scrollpane (if you have any) ?

                  Message was edited by:
                  ProZ
                  • 6. Re: JButton inside JTable Cell
                    843805
                    I refreshed my scrollpane and it works!
                    Thanks a lot!
                    • 7. Re: JButton inside JTable Cell
                      843805
                      iam facing the same problem you faced regarding the Jbutton in Jtable.


                      I would like to made the button disappear after the user click on it (or force it do setEnabled(false)......

                      how did u fixed this ...will be more help full if you replied me .
                      thanks in advance.

                      sathish.
                      • 8. Re: JButton inside JTable Cell
                        843805
                        Just use:
                        button.setVisible(false);
                        to hide your button, then refresh your scroll pane and table and use:
                        this.repaint();
                        If it still doesn't work. If your problem is still unsolved, remove the scroll pane and JTable and make some new ones. (not a very good solution, this will slow down your program...)
                        I hope I helped you out a little bit!
                        • 9. Re: JButton inside JTable Cell
                          843805
                          thanks ,. i tried the option and it worked well.

                          I have some other problem also , for some time i am setting the "button.SetEnabled(false); ", but when the user click on another table row my old button becomes visible automatically. How can I fix this things?!!??. Until i click the another button in that column , the button should be in disable state..how to make this work. ???

                          and also the action performed is called only once and after that it is not getting called if i use the setEnable(false) for the button .

                          really i have tried several options ...nothing helped.
                          • 10. Re: JButton inside JTable Cell
                            843806
                            hi camickr,

                            First of all thanks! Your code helps me a lot! :) Clear and fast, as I love its!

                            Do know that it's an old topic, but I've got a simple question. I'm not a swing expert, so hope this question would not sound stupid...
                            I pay attention to your code, and here is what I've concluded: (do know that it was a simple example)

                            you are using two components, since the TableCellRenderer and TableCellEditor are implemented in the same class: an editButton and a renderButton (for each method)

                            If we're digging into a set of components, such as a JPanel in a cell that contains a lot of labels, buttons and so on, does it mean that we must have, actually, two instances of each component? (one by interface, since our class implements each of it)

                            If my preceding assertion is true, what do you think of this?
                            columnModel.getColumn(column).setCellRenderer( this );
                            columnModel.getColumn(column).setCellEditor( this );
                            
                            // maybe this could do the trick (of course outside the ButtonColumn class
                            columnModel.getColumn(column).setCellRenderer( new  ButtonColumn());
                            columnModel.getColumn(column).setCellEditor( new ButtonColumn() );
                            Have a good day!

                            Mathieu.
                            • 11. Re: JButton inside JTable Cell
                              843806
                              This solution works beautifully - I only have one question:

                              I've modified some of my cells to support multi-line editing (as seen here: http://www.javaspecialists.co.za/archive/newsletter.do?issue=106&locale=en_US)

                              This now causes my button cells to expand to the full height of the row. I've tried setting the maximum size on the buttons, but that has no effect - it seems what the JTable does is take a snapshot of the renderer and expand the image to fill the cell, so setting the button size has no effect.

                              Anyone have any thoughts on how I can restrict the button height? If I happen to have a row with several lines, I don't want the button being any bigger than it thinks it should be (e.g., the button should only be one line).
                              • 12. Re: JButton inside JTable Cell
                                camickr
                                All components use a renderers are set to the size of the cell. So you could try using a panel as the renderer. Then add your button to the panel. That was the panel gets resized to the size of the cell and the button should stay the correct size.
                                • 13. Re: JButton inside JTable Cell
                                  843806
                                  Perfect! I wrapped both the renderButton and editButton in a JPanel and returned those for the render/edit components instead, and I get a button in the cell that's the size I want.

                                  Thanks again!!
                                  • 14. Re: JButton inside JTable Cell
                                    843806
                                    I'm sorry but i can't seem to work this issue out.
                                    I'll try to post some code without going over the top with unnecessary details like row height etc:

                                    MAIN(the main class is called ProvaRendererCells and extends JFRAME):
                                         
                                    public static void main(String[] args) {         
                                                    ProvaRendererCells frame = new ProvaRendererCells();;
                                             frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
                                             frame.pack();
                                             frame.setVisible(true);
                                    }
                                    constructor
                                           
                                    public ProvaRendererCells() {
                                             super("JTableButton Demo");
                                         DefaultTableModel tableModel = makeTableModel();
                                         JTable table = new JTable(tableModel);
                                             table.setDefaultRenderer(JButton.class, myRenderer);
                                           JScrollPane scrollPane = new JScrollPane(table);
                                                    setContentPane(scrollPane);
                                      }
                                    the TableModel
                                         
                                    private DefaultTableModel makeTableModel(){
                                              Vector rows = new Vector();
                                              Vector row1 = new Vector();
                                              Vector columns = new Vector();
                                              columns.addElement("");
                                              columns.addElement("");
                                              JButton bottoneA = new JButton("");
                                              bottoneA.setActionCommand("Button1");
                                              bottoneA.addActionListener((ActionListener)myRenderer);
                                                                    row1.addElement(bottoneA);
                                              row1.addElement(bottoneA);
                                              rows.addElement(row1);
                                              DefaultTableModel tableModel = new DefaultTableModel(rows, columns){
                                                                    @Override
                                                                    public Class getColumnClass(int column){
                                                                    return getValueAt(0, column).getClass();
                                                                    }
                                                                    };
                                              return tableModel;
                                         }
                                    and at last, the renderer and actionListener class MyRenderer
                                    class MyRenderer implements TableCellRenderer, ActionListener {
                                         public void actionPerformed(ActionEvent e) {
                                             System.out.println("---->WORKS");
                                                    }
                                        
                                         public Component getTableCellRendererComponent(JTable table, Object value,
                                                                  boolean isSelected, boolean hasFocus, int row, int column) {
                                              if(value instanceof Component){
                                                   return (Component)value;
                                              }
                                         }
                                    }
                                    In the end, the buttons are displayed correctly since:
                                    1) there is a renderer registered for them (using table.setDefaultRenderer(JButton.class, myRenderer);)
                                    2) the tableModel DefaultTableModel returns the right class for the column cells so the rendered at 1) is used

                                    What does not work, is the ActionListener, the ActionEvent is never triggered clicking the buttons in the cells.

                                    I'm quite lost, i'd really appreciate a hand.

                                    Thanks all and sorry for the english.
                                    Roberto
                                    1 2 Previous Next