Button does not work when code is added to Abstracttablemodel

Asked

Viewed 80 times

2

I created a test project to implement in a larger table project with a button as one of the row elements. It works perfectly, but when I try to add to my code the button does not perform the action that was programmed. It is being done with Abstracttablemodel. Does anyone have an idea where the problem might be?

Testable design of what I need to do:

Java table.

public class Tabela extends JFrame{

    public Tabela(){
        super("Teste de Componentes na Coluna");

        Object[][] data = {
            {"1", "Azul", new Integer(2013), "21"},
            {"2", "Roxo", new Integer(2013), "1"},
            {"3", "Preto", new Integer(2013), "2"},
            {"4", "Vermelho", new Integer(2013), "8"},
            {"5", "Rosa", new Integer(2013), "70"},
            {"6", "Verde", new Integer(2013), "10"}
        };

        String columnHeaders[] = {"Position", "Color", "Last Year Won", "Trophies"};


        JTable table = new JTable(data,columnHeaders);

        table.getColumnModel().getColumn(1).setCellRenderer(new ButtonRenderer());
        table.getColumnModel().getColumn(1).setCellEditor(new ButtonEditor(new JTextField()));

        JScrollPane pane = new JScrollPane(table);
        getContentPane().add(pane);
        setSize(450,100);

        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Tabela t = new Tabela();
        t.setVisible(true);
    }

    class ButtonRenderer extends JButton implements TableCellRenderer{

        public ButtonRenderer(){
            setOpaque(true);
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object obj, 
                boolean selected, boolean focused, int row, int col) {
            setText((obj == null) ? "":obj.toString());
            return this;
        }

    }

    class ButtonEditor extends DefaultCellEditor{
    protected JButton btn;
    private String lbl;
    private Boolean clicked;

    public ButtonEditor(JTextField txt){
        super(txt);
        btn = new JButton();
        btn.setOpaque(true);

        btn.addActionListener(new ActionListener(){
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        fireEditingStopped();
                    }
        });
    }

    public Component getTableCellEditorComponent(JTable table, Object obj, boolean selected, int row, int col){
        lbl = (obj == null) ? "":obj.toString();
        btn.setText(lbl);
        clicked = true;
        return btn;
    }

        public Object getCellEditorValue(){
    if(clicked){
        JOptionPane.showMessageDialog(btn, lbl + "Clicked");
    }
    clicked = false;
    return new String(lbl);
}

        public boolean stopCellEditing(){
                clicked = false;
                return super.stopCellEditing();
        }

        protected void fireEditingStopped(){
                super.fireEditingStopped();
        }
}

}

Project where the table should be aggregated:

Pendenciaview.java view.

public class PendenciaView extends JPanel {
    private JTextField txtId;

    PendenciaTableModel tableModel = new PendenciaTableModel();
    private final JTable table;

    /**
     * Create the panel.
     */
    public PendenciaView() {
        setLayout(null);
        setSize(794, 548);

        JLabel lblListaDePendencias = new JLabel("Lista de Pend\u00EAncias:");
        lblListaDePendencias.setBounds(10, 11, 120, 14);
        add(lblListaDePendencias);

        JLabel lblFiltrarPor = new JLabel("Filtrar por:");
        lblFiltrarPor.setBounds(10, 464, 60, 14);
        add(lblFiltrarPor);

        JLabel lblCategoria = new JLabel("Categoria:");
        lblCategoria.setBounds(89, 489, 60, 14);
        add(lblCategoria);

        JComboBox cmbCategoria = new JComboBox();
        cmbCategoria.setBounds(160, 486, 150, 20);
        cmbCategoria.addItem("Todas");
        cmbCategoria.addItem("Pedido");
        cmbCategoria.addItem("Produto");
        cmbCategoria.addItem("Categoria");
        cmbCategoria.addItem("Comprador");      
        add(cmbCategoria);

        JLabel lblDataDeInicio = new JLabel("Data de In\u00EDcio:");
        lblDataDeInicio.setBounds(327, 486, 90, 14);
        add(lblDataDeInicio);

        JDateChooser dcDataDeInicio = new JDateChooser();
        dcDataDeInicio.setBounds(427, 486, 130, 20);        
        add(dcDataDeInicio);
        dcDataDeInicio.setDateFormatString("dd/MM/yyyy");

        JLabel lblDataDeFim = new JLabel("Data de Fim:");
        lblDataDeFim.setBounds(567, 489, 77, 14);
        add(lblDataDeFim);

        JDateChooser dcDataDeFim = new JDateChooser();      
        dcDataDeFim.setBounds(654, 486, 130, 20);
        add(dcDataDeFim);
        dcDataDeFim.setDateFormatString("dd/MM/yyyy");

        JLabel lblId = new JLabel("ID:");
        lblId.setBounds(10, 489, 15, 14);
        add(lblId);

        txtId = new JTextField();
        txtId.setBounds(28, 486, 51, 20);
        add(txtId);
        txtId.setColumns(10);

        JButton btnFiltrar = new JButton("Filtrar");
        btnFiltrar.setBounds(695, 514, 89, 23);
        add(btnFiltrar);

        JPanel panel = new JPanel();
        panel.setBounds(10, 31, 774, 380);
        add(panel);
        panel.setLayout(null);

        table = new JTable(tableModel);
        table.setBounds(0, 0, 774, 380);
        panel.add(table);

        JScrollPane scrollPane = new JScrollPane(table);
        scrollPane.setBounds(0, 0, 774, 380);
        panel.add(scrollPane);

        table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);

        JButton btnRemoverPendencias = new JButton("Remover Pend\u00EAncias");
        btnRemoverPendencias.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                //Remove uma linha
                if(table.getSelectedRow() != -1){
                      tableModel.removeRow(table.getSelectedRow());
                }
            }
        });
        btnRemoverPendencias.setBounds(10, 422, 157, 23);
        add(btnRemoverPendencias);

        //"Selecionar", "ID", "Pendência", "Data e Hora", "Descrição", "Detalhes"
        table.getColumnModel().getColumn(0).setMaxWidth(70);
        table.getColumnModel().getColumn(1).setMaxWidth(50);
        table.getColumnModel().getColumn(2).setMaxWidth(180);
        table.getColumnModel().getColumn(3).setMaxWidth(100);
        table.getColumnModel().getColumn(4).setMaxWidth(300);
        table.getColumnModel().getColumn(5).setMaxWidth(80);

        PendenciaModel pm = new PendenciaModel();
        pm.setSelecionado(true);
        pm.setId(1);
        pm.setPendencia("BlaBlaBla");
        Date d = new Date();
        pm.setDataHora(d);
        pm.setDescricao("Erafoene vpanpvev np aevnrvpnaep");
        pm.setDetalhes("Abrir");

        tableModel.addRow(pm);

        PendenciaModel pm2 = new PendenciaModel();
        pm2.setSelecionado(true);
        pm2.setId(2);
        pm2.setPendencia("Vdioandd");
        Date d2 = new Date();
        pm2.setDataHora(d2);
        pm2.setDescricao("abdcdgae aefin aefioanfe aiefn");
        pm2.setDetalhes("Abrir");

        tableModel.addRow(pm2);

        Object[][] data = {
                {true, 1, "Azul", new Date(), "Bçlasncaio evwiwwe wavejh", "Abrir"},
                {true, 1, "Roxo", new Date(), "Bçlasncaio evwiwwe wavejh", "Abrir"},
                {true, 1, "Verde", new Date(), "Bçlasncaio evwiwwe wavejh", "Abrir"},
                {true, 1, "Rosa", new Date(), "Bçlasncaio evwiwwe wavejh", "Abrir"},
                {true, 1, "Branco", new Date(), "Bçlasncaio evwiwwe wavejh", "Abrir"},
            };


        table.getColumnModel().getColumn(5).setCellRenderer(new ButtonRenderer());
        table.getColumnModel().getColumn(5).setCellEditor(new ButtonEditor(new JTextField()));


    }

       class ButtonRenderer extends JButton implements TableCellRenderer{

            public ButtonRenderer(){
                setOpaque(true);
            }

            @Override
            public Component getTableCellRendererComponent(JTable table, Object obj, 
                    boolean selected, boolean focused, int row, int col) {
                setText((obj == null) ? "":obj.toString());
                return this;
            }

        }

        class ButtonEditor extends DefaultCellEditor{
        protected JButton btn;
        private String lbl;
        private Boolean clicked;

        public ButtonEditor(JTextField txt){
            super(txt);
            btn = new JButton();
            btn.setOpaque(true);

            btn.addActionListener(new ActionListener(){
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            fireEditingStopped();
                        }
            });
        }

        public Component getTableCellEditorComponent(JTable table, Object obj, boolean selected, int row, int col){
            lbl = (obj == null) ? "":obj.toString();
            btn.setText(lbl);
            clicked = true;
            return btn;
        }

            public Object getCellEditorValue(){
        if(clicked){
            JOptionPane.showMessageDialog(btn, lbl + "Clicked");
        }
        clicked = false;
        return new String(lbl);
    }

            public boolean stopCellEditing(){
                    clicked = false;
                    return super.stopCellEditing();
            }

            protected void fireEditingStopped(){
                    super.fireEditingStopped();
            }
    }


}

Pendenciatablemodel.java

public class PendenciaTableModel extends AbstractTableModel {


    private List<PendenciaModel> dados = new ArrayList<>();
    private String[] colunas = {"Selecionar", "ID", "Pendência", "Data e Hora", "Descrição", "Detalhes"};

    @Override
    public String getColumnName(int column){
        return colunas[column];
    }

    @Override
    public int getColumnCount() {
        return colunas.length;
    }

    @Override
    public int getRowCount() {
        return dados.size();
    }

    @Override
    public Object getValueAt(int linha, int coluna) {
        switch(coluna){
            case 0:
                return dados.get(linha).getSelecionado();
            case 1:
                return dados.get(linha).getId();
            case 2:
                return dados.get(linha).getPendencia();
            case 3:
                return dados.get(linha).getDataHora();
            case 4:
                return dados.get(linha).getDescricao();
            case 5:
                return dados.get(linha).getDetalhes();
        }

        return null;
    }

    public void addRow(PendenciaModel pm) {
        this.dados.add(pm);
        this.fireTableDataChanged();    
    }

    public void removeRow(int linha){
        this.dados.remove(linha);
        this.fireTableRowsDeleted(linha, linha);
    }



}

Pendenciamodel.java model.

public class PendenciaModel { 
    private boolean selecionado;
    private int id;
    private String pendencia;
    private Date dataHora;
    private String descricao;
    private String detalhes;

    public boolean getSelecionado() {
        return selecionado;
    }
    public void setSelecionado(boolean selecionado) {
        this.selecionado = selecionado;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getPendencia() {
        return pendencia;
    }
    public void setPendencia(String pendencia) {
        this.pendencia = pendencia;
    }
    public Date getDataHora() {
        return dataHora;
    }
    public void setDataHora(Date dataHora) {
        this.dataHora = dataHora;
    }
    public String getDescricao() {
        return descricao;
    }
    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }
    public String getDetalhes() {
        return detalhes;
    }
    public void setDetalhes(String detalhes) {
        this.detalhes = detalhes;
    }


}
  • I have a menu (Jmenubar) where I put in the click action to add an instance of Pendenciaview on the screen. getContentPane(). add(new Pendenciaview()); (It is a Jframe and I am working with Cardlayout)

  • Right, what the code needs to do that doesn’t?

2 answers

1

Your model does not allow data editing - documentation of the method isCellEditable of AbstractTableModel: "Returns false." i.e., no cell will be editable, the respective CellEditor will never be called, so the button will not be activated.

Solution, override the method isCellEditable to allow editing of the respective column:

public class PendenciaTableModel extends AbstractTableModel {

    ...

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return columnIndex == 5 || super.isCellEditable(rowIndex, columnIndex);
    }
}

Obs:

  1. instead of using directly literal (example 5) to identify columns, it is preferable to use constants private static final int COL_DETALHE = 5;

  2. (obviously) the above solution also goes to allow editing of other columns

  • This way you still need to give 2 clicks (one for editing) to work.

  • Your reply was also very helpful. Thanks for your help.

1


The way you’re doing, in addition to incorrectly using the DefaultCellEditor, waiting for a JTextField and you’re wearing a JButton, also have difficulties later to retrieve the button line object.

I would like to propose a more robust solution, which does not need to use editors or render, created by the user camickr, where the class Buttoncolumn adds a button in each column of the table automatically, leaving you only the part of defining the action to be taken when there is the click.

To configure in your code, just copy the link class to your project and instantiate as below:

ButtonColumn buttonColumn = new ButtonColumn(table, action, columnIndex);

where table is your table, action is the action that the button will have and columnIndex is the index of the column where the button will be displayed.

For demonstration purposes, I created the action below that displays the line that was clicked:

Action mostrarDetalhes = new AbstractAction() {

    @Override
    public void actionPerformed(ActionEvent e) {
        //recupera a tabela
        JTable table = (JTable)e.getSource();
        //recupera a linha onde houve o clique
        int modelRow = Integer.valueOf(e.getActionCommand());
        JOptionPane.showMessageDialog(null, "Linha " + modelRow + " foi clicada");

    }
};

ButtonColumn buttonColumn = new ButtonColumn(table, mostrarDetalhes, 5);

The result of this example implemented in your code is:

inserir a descrição da imagem aqui

Just pointing out the class author’s warning, the column needs to be editable, so it is also necessary to apply Carlos' reply tip.

  • It worked perfectly. Again, thanks for the availability and for the patience.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.