• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 402
  • Last Modified:

JButtons in a column

I am having trouble adding JButtons to a entire column of a JTable.

I have a 3X5 table, and I want the last column to all consist of buttons.

If possible, please provide some sample code. Thanks!
0
dshrenik
Asked:
dshrenik
  • 11
  • 4
1 Solution
 
for_yanCommented:
0
 
for_yanCommented:
It is probably ecven easiier to do it just using TableCellRenderer (I think we did GIFs with you in one of the  columns)
So the same idea , only the method returns Componet so you can check which column and return eiother label or button detpendning on the
column
0
 
for_yanCommented:

this is not 3x5 but the fisrt column is buttons
ansd I made it from
http://www.roseindia.net/java/example/java/swing/CustomCellRenderer.shtml
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;

public class CustomCellRenderer{
  JTable table;
  TableColumn tcol;
  public static void main(String[] args) {
  new CustomCellRenderer();
  }

  public CustomCellRenderer(){
  JFrame frame = new JFrame("Creating a Custom Cell Reanderer!");
  JPanel panel = new JPanel();
  String data[][] = {{"Vinod","Computer","3"},
   {"Rahul","History","2"},
   {"Manoj","Biology","4"},
   {"Sanjay","PSD","5"}};
  String col [] = {"Name","Course","Year"};
  DefaultTableModel model = new DefaultTableModel(data,col);
  table = new JTable(model);
  tcol = table.getColumnModel().getColumn(0);
  tcol.setCellRenderer(new CustomTableCellRenderer());
  tcol = table.getColumnModel().getColumn(1);
  tcol.setCellRenderer(new CustomTableCellRenderer());
  tcol = table.getColumnModel().getColumn(2);
  tcol.setCellRenderer(new CustomTableCellRenderer());
  JTableHeader header = table.getTableHeader();
  header.setBackground(Color.yellow);
  JScrollPane pane = new JScrollPane(table);
  panel.add(pane);
  frame.add(panel);
  frame.setSize(500,150);
  frame.setUndecorated(true);
  frame.getRootPane().setWindowDecorationStyle(JRootPane.PLAIN_DIALOG);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setVisible(true);
  }

  public class CustomTableCellRenderer extends DefaultTableCellRenderer{
  public Component getTableCellRendererComponent (JTable table,
Object obj, boolean isSelected, boolean hasFocus, int row, int column) {
  //Component cell = super.getTableCellRendererComponent(
   //table, obj, isSelected, hasFocus, row, column);
      if(column == 0){
          JButton btn = new JButton(obj.toString());
          return btn;
      }
      else
      {
          JLabel lbl = new JLabel(obj.toString());
          return lbl;
      }

  }
}
}

Open in new window

0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
dshrenikAuthor Commented:
That is working fine, but I cannot add actionlisteneres.
0
 
for_yanCommented:
Why do you want to do it - we already were talking that it is better to get mosuseEvents form the table
then actionListeners form buttons inside the table
0
 
dshrenikAuthor Commented:
That's right, but the problem is I am using a smaller button that does not occupy the entire cell, and I want an action to be performed only when the user clicks the button and not anywhere in the cell.
0
 
for_yanCommented:

I think you need to make Cell editable in table model
then it will listen to events
you need to override
public boolean isCellEditable(int row, int column) {
return true;
}
0
 
dshrenikAuthor Commented:
That did not work.
0
 
for_yanCommented:
it is too complex - you can read about how to do it here,
but it is better to come up with simpler design:

http://www.devx.com/getHelpOn/10MinuteSolution/20425
0
 
for_yanCommented:
Yes this one works and lisstens to clicks,
but indeed looks too complex
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.awt.event.*;

class JTableButtonRenderer implements TableCellRenderer {
  private TableCellRenderer __defaultRenderer;

  public JTableButtonRenderer(TableCellRenderer renderer) {
    __defaultRenderer = renderer;
  }

  public Component getTableCellRendererComponent(JTable table, Object value,
						 boolean isSelected,
						 boolean hasFocus,
						 int row, int column)
  {
    if(value instanceof Component)
      return (Component)value;
    return __defaultRenderer.getTableCellRendererComponent(
	   table, value, isSelected, hasFocus, row, column);
  }
}

class JTableButtonModel extends AbstractTableModel {
  private Object[][] __rows = {
      { "One", new JButton("Button One") },
      { "Two", new JButton("Button Two") },
      { "Three", new JButton("Button Three") },
      { "Four", new JButton("Button Four") }
    };

  private String[] __columns = { "Numbers", "Buttons" };

  public String getColumnName(int column) {
    return __columns[column];
  }

  public int getRowCount() {
    return __rows.length;
  }

  public int getColumnCount() {
    return __columns.length;
  }

  public Object getValueAt(int row, int column) {
      return __rows[row][column];
  }

  public boolean isCellEditable(int row, int column) {
    return false;
  }

  public Class getColumnClass(int column) {
    return getValueAt(0, column).getClass();
  }
}

class JTableButtonMouseListener implements MouseListener {
  private JTable __table;

  private void __forwardEventToButton(MouseEvent e) {
    TableColumnModel columnModel = __table.getColumnModel();
    int column = columnModel.getColumnIndexAtX(e.getX());
    int row    = e.getY() / __table.getRowHeight();
    Object value;
    JButton button;
    MouseEvent buttonEvent;

    if(row >= __table.getRowCount() || row < 0 ||
       column >= __table.getColumnCount() || column < 0)
      return;

    value = __table.getValueAt(row, column);

    if(!(value instanceof JButton))
      return;

    button = (JButton)value;

    buttonEvent =
      (MouseEvent)SwingUtilities.convertMouseEvent(__table, e, button);
    button.dispatchEvent(buttonEvent);
    // This is necessary so that when a button is pressed and released
    // it gets rendered properly.  Otherwise, the button may still appear
    // pressed down when it has been released.
    __table.repaint();
  }

  public JTableButtonMouseListener(JTable table) {
    __table = table;
  }

  public void mouseClicked(MouseEvent e) {
    __forwardEventToButton(e);
  }

  public void mouseEntered(MouseEvent e) {
    __forwardEventToButton(e);
  }

  public void mouseExited(MouseEvent e) {
    __forwardEventToButton(e);
  }

  public void mousePressed(MouseEvent e) {
    __forwardEventToButton(e);
  }

  public void mouseReleased(MouseEvent e) {
    __forwardEventToButton(e);
  }
}

 final class JTableButton extends JFrame {
  private JTable __table;
  private JScrollPane __scrollPane;

  public JTableButton() {
    super("JTableButton Demo");
    TableCellRenderer defaultRenderer;

    __table = new JTable(new JTableButtonModel());
    defaultRenderer = __table.getDefaultRenderer(JButton.class);
    __table.setDefaultRenderer(JButton.class,
			       new JTableButtonRenderer(defaultRenderer));
    __table.setPreferredScrollableViewportSize(new Dimension(400, 200));
    __table.addMouseListener(new JTableButtonMouseListener(__table));

    __scrollPane = new JScrollPane(__table);
    setContentPane(__scrollPane);
  }

  public static void main(String[] args) {
    Frame frame;
    WindowListener exitListener;

    exitListener = new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
	Window window = e.getWindow();
	window.setVisible(false);
	window.dispose();
	System.exit(0);
      }
    };

    frame = new JTableButton();
    frame.addWindowListener(exitListener);
    frame.pack();
    frame.setVisible(true);
  }
}

Open in new window

0
 
dshrenikAuthor Commented:
0
 
for_yanCommented:
Yes, that article mostly leads tyo anlysing the position of moouse clicking - you can probably with that even figure out if it was clicked insde the button
inside the cell. The one form www.devx.com works, but it has the whole cell made up of button
(so that we again could have used that mouse.atPoint() method for simplicity instead).
In general it shows the way how to go to cells made up of custom element say containg label and button.
However it does not seem so strightforward to modify it to such components.
0
 
for_yanCommented:
No, this www.devx.com does not give any other way either.
The problem is that JTable captures events - so you need then analyze
location of the event and then distinguish if that was on button or on
sioomething else in the same cell. It is probably possible but not so simple.
0
 
for_yanCommented:

This is JTable with buttons within cells which responds only
to clicks on the buttons but not on the enclosing cell:

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

//this is taken from   http://stackoverflow.com/questions/3606864/jtable-buttons-in-custom-panel-in-cell/3606915#3606915
// but modified as it was not compiling

public class MyClassTable  {
    public static void main(String[] args) {


        ArrayList<MyClass>ar = new ArrayList<MyClass>();
        ar.add(new MyClass("a","b"));
        ar.add(new MyClass("c","d"));
         ar.add(new MyClass("e","f"));

        JTable myClassTable = new JTable(new MyClassTableModel(ar));
        myClassTable.setDefaultRenderer(MyClass.class, new MyClassCellRenderer());
        myClassTable.setDefaultEditor(MyClass.class, new MyClassCellEditor());
        myClassTable.setRowHeight(100);

        JFrame jf = new JFrame();
        jf.add(new JScrollPane(myClassTable));
        jf.setSize(300,330);
        jf.setVisible(true);


    }

}

class MyClassTableModel extends DefaultTableModel {
  ArrayList<MyClass> data;

  public MyClassTableModel(ArrayList<MyClass> data) {
    this.data = data;
  }

  public Class<?> getColumnClass(int columnIndex) {
      if(columnIndex ==0)
      return MyClass.class;
     else return String.class;}
  public int getColumnCount() { return 2; }
  public String getColumnName(int columnIndex) { if(columnIndex ==0) return "MyClass";
  else return "Just string";}
  public int getRowCount() { return (data == null) ? 0 : data.size(); }
  public Object getValueAt(int rowIndex, int columnIndex) {if(columnIndex ==0) return data.get(rowIndex);
  else return data.get(rowIndex).getString1();}
  public boolean isCellEditable(int rowIndex, int columnIndex) { return true; }
}


class MyClassCellComponent extends JPanel implements ActionListener {
  MyClass mc;
    JButton btn;
    JLabel lbl;

  public MyClassCellComponent(MyClass mc) {
      this.mc = mc;

        btn = new JButton(mc.getString1());
      btn.addActionListener(this);
    lbl = new JLabel(mc.getString2());

    this.setLayout(new FlowLayout());
    this.add(lbl);
    this.add(btn);


    // initialize components (labels, buttons, etc.)
    // add action listeners
  }

   public void actionPerformed (ActionEvent ae){
       System.out.println("click");
      if(ae.getSource() instanceof JButton){
         System.out.println(((JButton)ae.getSource()).getText());
      }

   }

  public void updateData(MyClass myClass, boolean isSelected, JTable table) {
    this.mc = myClass;
      btn.setText(myClass.getString1());
         lbl.setText(myClass.getString2());
    // update buttons, labels etc. accordingly
  }
}

class MyClassCellRenderer implements TableCellRenderer {


  public MyClassCellRenderer() {
  //  panel = new MyClassCellComponent();
  }

  public Component getTableCellRendererComponent(JTable table, Object value,        boolean isSelected, boolean hasFocus, int row, int column) {
      if(column == 0){
    MyClass myClass = (MyClass)value;
       MyClassCellComponent panel = new      MyClassCellComponent(myClass);
    panel.updateData(myClass, isSelected, table);
    return panel; }
      else{
          JLabel jl = new JLabel(value.toString());
          return jl;
      }

  }
}

class MyClassCellEditor extends AbstractCellEditor implements TableCellEditor{


  public MyClassCellEditor() {

    //panel = new MyClassCellComponent();
  }
  public Component getTableCellEditorComponent(JTable table, Object value,      boolean isSelected, int row, int column) {
                   if(column == 0){
    MyClass myClass = (MyClass)value;
       MyClassCellComponent panel = new      MyClassCellComponent(myClass);
    panel.updateData(myClass, true, table);
    return panel;
                   }
      else{
          JLabel jl = new JLabel(value.toString());
          return jl;
      }
  }
  public Object getCellEditorValue() {
    return null;
  }

   
   public boolean stopCellEditing() {
       return true;

   }


}

class MyClass {
    String s1;
    String s2;
    public MyClass(String s1, String s2){
        this.s1 = s1;
        this.s2 = s2;
    }
  public String getString1(){return s1;}
   public String getString2(){return s2;}


}

Open in new window

0
 
for_yanCommented:
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 11
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now