Making a JButton clickable inside a JTable

前端 未结 6 1555
滥情空心
滥情空心 2020-12-05 23:38

Here is the screenshot of what I want to do :

\"enter

What\'s happening there

相关标签:
6条回答
  • 2020-12-06 00:03

    This Table Button Column from Rob Camick may fit your needs.

    0 讨论(0)
  • 2020-12-06 00:04

    This articles provides an easier approach to your problem without adding MouseListeners and computing if the click is actually on the button or not:

    http://web.archive.org/web/20100623105810/http://ivolo.mit.edu/post/A-Simple-Pattern-for-Embedding-Components-into-a-Swing-JTable.aspx

    0 讨论(0)
  • 2020-12-06 00:05

    Here is my solution

    ButtonEditor.java

    public abstract class ButtonEditor extends DefaultCellEditor implements ActionListener {
    private static final long serialVersionUID = 1L;
    
    /** The cell's row. */
    protected int row;
    
    /** The cell's column. */
    protected int column;
    
    /** The cell's column. */
    protected JTable table;
    
    /** The button we are editing. */
    protected JButton button;
    
    /** The panel used when editing. */
    protected JPanel panel = new JPanel(new GridBagLayout());
    
    /** Constructor */
    public ButtonEditor() {super(new JCheckBox());}
    
    /**
     * This method is called when the user try to modify a cell. 
     * In this case it will be called whenever the user click on the cell.
     * @param table
     * @param value
     * @param isSelected
     * @param row
     * @param column
     * @return JPanel The JPanel returned contains a JButton with an ActionListener. 
     */
    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 
        this.row = row;
        this.column = column;
        this.table = table;
        button = (JButton) value;
    
        //prevent to add the action listener everytime the user click on the cell.
        if(button.getActionListeners().length == 0) button.addActionListener(this); 
    
        panel.add(button);
        panel.setBackground(table.getGridColor());
        return panel;
    }
    
    /**
     * Return a renderer for JButtons. The result is a button centered in the table's cell.
     * @return
     */
    public static TableCellRenderer getRenderer() {
        return new TableCellRenderer() {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                JPanel panel = new JPanel(new GridBagLayout());
                panel.add((JButton) value);
                panel.setBackground(table.getGridColor());
                return panel;
            }
        };
    }
    

    }

    And here is how to use it:

    Demo.java

        table.setDefaultRenderer(JButton.class, ButtonEditor.getRenderer()); 
        table.setDefaultEditor(JButton.class, new ButtonEditor() {
            @Override
            public void actionPerformed(ActionEvent e) {
    
                //handle clicks here. for example:   
                if(column == 5) {
                    System.out.Println(row);
                    button.setFocusPainted(false);                  
                }
            }
        });
    
    0 讨论(0)
  • 2020-12-06 00:08

    The problem is that the JButton no longer exists when painted in the table. Those components are only used to create a 'stamp' when the table is rendered. There is no actual button present.

    There is a way to allow you to click on the button, and still keep your table non-editable, but it is far from proper code. Just a quick outline for a possible solution (I do not have the time at this moment to give a full code example)

    • attach a mouse listener to the table
    • when you receive a mouse click, determine the cell in which the mouse click occurred
    • ask the table renderer for the component for that cell
    • use the location of the mouse click to determine whether a button is present in the component from the previous step at that particular location
    • if so, do the click through the button api (the doClick method)

    And this is not even the dirty part of the code. Since your renderer (hopefully) does not return a new JButton each time, you should in your ActionListener which is attached to the JButton keep track of for which component the click actually occurred. A possible solution is to keep a reference to the table model value for which you the last time created a JButton (so in the getCellRendererComponent method keep track of the row/column), but I am unsure whether this is the best approach.

    As said, a possible solution but far from elegant.

    The easiest way is to just make that one column editable and use an editor, as pointed out in other answers

    0 讨论(0)
  • 2020-12-06 00:20

    Overload your Table model, and set isCellEditable(int, int) return false for the cells with buttons.

    It works great in with a MouseListener added to the table.

    0 讨论(0)
  • 2020-12-06 00:26

    Try this:

    import java.awt.Color;
    import java.awt.Component;
    import java.awt.EventQueue;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.DefaultCellEditor;
    import javax.swing.JButton;
    import javax.swing.JCheckBox;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.UIManager;
    import javax.swing.table.DefaultTableModel;
    import javax.swing.table.TableCellRenderer;
    import javax.swing.table.TableModel;
    
    public class TableWithButtonDemo
    {
      private JFrame frame = new JFrame("Table Demo");
      private String[] columnNames = { "String", "Integer", "Float", "" };
      private Object[][] data = { { "Dummy", new Integer(12), new Float(12.15), "Consulter" } };
      private TableModel model = new DefaultTableModel(data, columnNames)
      {
        private static final long serialVersionUID = 1L;
    
        public boolean isCellEditable(int row, int column)
        {
          return column == 3;
        }
      };
      private JTable table = new JTable(model);
    
      public TableWithButtonDemo()
      {
        table.getColumnModel().getColumn(3).setCellRenderer(new ClientsTableButtonRenderer());
        table.getColumnModel().getColumn(3).setCellEditor(new ClientsTableRenderer(new JCheckBox()));
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        table.setShowHorizontalLines(true);
        table.setShowVerticalLines(false);
    
        JScrollPane scroll = new JScrollPane(table);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(scroll);
        frame.pack();
        frame.setLocation(150, 150);
        frame.setVisible(true);
      }
    
      public static void main(String[] args) throws Exception
      {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        EventQueue.invokeLater(new Runnable()
        {
          public void run()
          {
            new TableWithButtonDemo();
          }
        });
      }
    
      class ClientsTableButtonRenderer extends JButton implements TableCellRenderer
      {
        public ClientsTableButtonRenderer()
        {
          setOpaque(true);
        }
    
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
        {
          setForeground(Color.black);
          setBackground(UIManager.getColor("Button.background"));
          setText((value == null) ? "" : value.toString());
          return this;
        }
      }
      public class ClientsTableRenderer extends DefaultCellEditor
      {
        private JButton button;
        private String label;
        private boolean clicked;
        private int row, col;
        private JTable table;
    
        public ClientsTableRenderer(JCheckBox checkBox)
        {
          super(checkBox);
          button = new JButton();
          button.setOpaque(true);
          button.addActionListener(new ActionListener()
          {
            public void actionPerformed(ActionEvent e)
            {
              fireEditingStopped();
            }
          });
        }
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
        {
          this.table = table;
          this.row = row;
          this.col = column;
    
          button.setForeground(Color.black);
          button.setBackground(UIManager.getColor("Button.background"));
          label = (value == null) ? "" : value.toString();
          button.setText(label);
          clicked = true;
          return button;
        }
        public Object getCellEditorValue()
        {
          if (clicked)
          {
            JOptionPane.showMessageDialog(button, "Column with Value: "+table.getValueAt(row, 1) + " -  Clicked!");
          }
          clicked = false;
          return new String(label);
        }
    
        public boolean stopCellEditing()
        {
          clicked = false;
          return super.stopCellEditing();
        }
    
        protected void fireEditingStopped()
        {
          super.fireEditingStopped();
        }
      }
    
    }
    
    0 讨论(0)
提交回复
热议问题