setvalueat setmodel columnas autoresizemode agregar java swing jtable

columnas - setmodel java



TableModel setCellEditable y configurando automáticamente el valor de nuevo en falso (1)

pero, ¿en qué parte de mi código debería cambiar la celda a no editable cuando se pierde el foco? -

Tú podrías:

  1. anula el setValueAt(...) de su TableModel para que una celda no sea editable una vez que se modifican los datos.

  2. use TableModelListener un evento cuando se actualicen los datos de una celda.

Actualmente estoy tratando de implementar un JPopupMenu en mi JTable que permite desbloquear una celda para editar usando

@Override public void actionPerformed(ActionEvent e){ if(e.getActionCommand() == "Unlock"){ pTableModel.setCellEditable(this.getSelectedRow(), this.getSelectedColumn(), true); } }

Este es el método relacionado en TableModel

public void setCellEditable(int row, int col, boolean value) { editableCells[row][col] = value; this.fireTableCellUpdated(row, col); // I don''t think I actually need this //because nothing in the cell has changed yet? }

isCellEditable() luego devuelve el valor de la matriz editableCells [] []. pero, ¿en qué parte de mi código debería cambiar la celda a no editable cuando se pierde el foco?

En una nota ligeramente relacionada, también me gustaría que la célula se enfoque inmediatamente. He leído sobre getEditorComponent().requestFocus() - pero eso no parece del todo correcto porque no se está editando nada en ese momento, la celda solo está seleccionada (y el uso de ese método arroja una nullpointereception que parece apoyar mi pensamiento proceso).

¿Puede alguien señalarme en la dirección correcta, por favor? No puedo ver dónde me estoy equivocando. Gracias

** Editar: para bloquear la celda cuando se pierde el foco intenté agregar un dispositivo celular personalizado con un focusListener:

private class CustomCellRenderer extends DefaultTableCellRenderer{ public CustomCellRenderer(){ addFocusListener(new FocusAdapter(){ @Override public void focusLost(FocusEvent e) { pTableModel.setCellEditable(getSelectedRow(), getSelectedColumn(), false); } }); } }

pero eso tampoco parece haber funcionado, pero probablemente lo estoy implementando incorrectamente (aunque he comprobado que se ha agregado el renderizador)

SSCCE

import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.table.AbstractTableModel; public class CellTest { public static void main(String[] args){ SwingUtilities.invokeLater(new Runnable(){ @Override public void run(){ createAndShowGUI(); } }); } private static void createAndShowGUI(){ JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); MyPanel panel = new MyPanel(); f.add(panel); f.pack(); f.setVisible(true); } } class MyPanel extends JPanel implements ActionListener{ private JTable table; private MyTableModel model; private JScrollPane sp; private List<Person> people; MyPanel(){ people = new ArrayList<>(); people.add(new Person("Will", 1)); model = new MyTableModel(people); table = new JTable(model); table.addMouseListener(new MouseAdapter(){ @Override public void mousePressed(MouseEvent e){ maybeShowPopup(e); } @Override public void mouseReleased(MouseEvent e){ maybeShowPopup(e); } }); table.setFillsViewportHeight(true); sp = new JScrollPane(table); this.add(sp); } @Override public void actionPerformed(ActionEvent e){ if(e.getActionCommand().equals("Unlock")) { model.setCellEditable(table.getSelectedRow(),table.getSelectedColumn(),true); } } private JPopupMenu createPopupMenu(){ JPopupMenu pop = new JPopupMenu(); JMenuItem item = new JMenuItem("Unlock"); item.addActionListener(this); pop.add(item); return pop; } private void maybeShowPopup(MouseEvent e){ int currentRow = table.rowAtPoint(e.getPoint()); if(currentRow >= 0 && currentRow < table.getRowCount()) table.setRowSelectionInterval(currentRow, currentRow); else table.clearSelection(); if(table.getSelectedRow() < 0) return; if(e.isPopupTrigger() && e.getComponent() instanceof JTable){ JPopupMenu pop = createPopupMenu(); pop.show(e.getComponent(), e.getX(), e.getY()); } } }

Y el TableModel y la clase de datos:

class MyTableModel extends AbstractTableModel{ private List<Person> data; private String[] colNames = new String[]{"Name","Age"}; private boolean[][] editableCells; public MyTableModel(List<Person> data){ this.data = data; this.editableCells = new boolean[this.getRowCount()][this.getColumnCount()]; } @Override public int getRowCount() { return data.size(); } @Override public int getColumnCount() { return colNames.length; } @Override public Object getValueAt(int row, int col){ Person p = data.get(row); switch(col){ case 0 : return p.getName(); case 1 : return p.getAge(); } return null; } @Override public boolean isCellEditable(int row, int col){ return editableCells[row][col]; } public void setCellEditable(int row, int col, boolean value){ editableCells[row][col] = value; } @Override public void setValueAt(Object value, int row, int col){ Person p = data.get(row); switch(col){ case 0 : p.setName((String)value);break; case 1 : p.setAge((int)value);break; } this.setCellEditable(row, col, false); this.fireTableCellUpdated(row, col); } public void setData(List<Person> data){ this.data = data; this.fireTableDataChanged(); } } class Person { private String name; private int age; public Person(String name, int age){ this.name = name; this.age = age; } public void setName(String name){ this.name = name;} public String getName(){ return name; } public void setAge(int age){ this.age = age;} public int getAge(){ return age; } }

Disculpas por la duración: no sabía cómo acortarlo sin quizás recrear lo que quería lograr. Hay un error en este código porque al hacer clic con el botón derecho y ''Desbloquear'' debe haber hecho ya clic en una fila, de lo contrario será una excepción arrayIndexOutOfBounds. Todavía no he podido encontrar la causa exacta.

Pero básicamente cuando haces clic derecho y luego seleccionas desbloquear, me gustaría que el cursor aparezca en la celda. En este momento, haga clic en desbloquear y luego haga doble clic en la celda.