Einstellung Ich versuche zur Zeit eine JPopupMenu in meinem JTable zu implementieren, die die Entriegelung einer Zelle für die Bearbeitung ermöglicht mitTablemodel setCellEditable und automatisch den Wert zurück auf false
@Override
public void actionPerformed(ActionEvent e){
if(e.getActionCommand() == "Unlock"){
pTableModel.setCellEditable(this.getSelectedRow(), this.getSelectedColumn(), true);
}
}
Dies ist ein verwandtes Verfahren in dem 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()
gibt dann den Wert des editableCells [] [] Array. Aber wo in meinem Code sollte ich die Zelle zurück zu uneditable ändern, wenn der Fokus verloren geht?
Zu einer etwas verwandten Anmerkung möchte ich auch, dass die Zelle sofort den Fokus erhält. Ich habe über getEditorComponent().requestFocus()
gelesen - aber das scheint nicht ganz richtig zu sein, weil zu dieser Zeit nichts bearbeitet wird, die Zelle wird nur ausgewählt (und die Verwendung dieser Methode löst eine Null-Null-Wahrnehmung aus, die meinen Denkprozess zu unterstützen scheint).
Kann mir bitte jemand in die richtige Richtung zeigen? Ich kann nicht sehen, wo ich falsch liege.
Dank** Edit: Für die Zelle zu verriegeln, wenn Fokus verloren habe ich versucht, eine benutzerdefinierte Zellrenderer mit einem focuslistener Zusatz:
private class CustomCellRenderer extends DefaultTableCellRenderer{
public CustomCellRenderer(){
addFocusListener(new FocusAdapter(){
@Override
public void focusLost(FocusEvent e) {
pTableModel.setCellEditable(getSelectedRow(), getSelectedColumn(), false);
}
});
}
}
aber das scheint nicht zu funktionieren, aber ich bin wahrscheinlich die Umsetzung es falsch (obwohl ich überprüft haben, dass der Renderer hinzugefügt wurde)
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());
}
}
}
Und das Tablemodel und Datenklasse:
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; }
}
Apologies für die Länge - ich wusste nicht, wie es kürzer zu machen, ohne vielleicht schlecht neu zu erstellen, was ich erreichen wollte. In diesem Code liegt ein Fehler darin, dass Sie mit der rechten Maustaste und der Schaltfläche "Entsperren" auf eine Zeile bereits geklickt haben müssen, da es sich andernfalls um eine arrayIndexOutOfBounds-Ausnahme handelt. Ich konnte die genaue Ursache noch nicht finden.
Aber im Grunde, wenn Sie mit der rechten Maustaste klicken und dann Entsperren auswählen, möchte ich den Cursor in der Zelle angezeigt werden. In dem Moment klicken Sie auf Entsperren und müssen dann auf die Zelle doppelklicken.
Ein Renderer ist keine echte Komponente. Es wird nur verwendet, um ein Bild einer Komponente zu zeichnen. Es wird nie den Fokus bekommen. Verwenden Sie nicht "==", um Strings zu vergleichen. Verwenden Sie die 'equals (...)' Methode. Veröffentlichen Sie eine ordnungsgemäße [mcve], die das Problem veranschaulicht. – camickr
Entschuldigung, es ist nicht so minimal, aber ich habe ein voll funktionierendes Beispiel mit einer Beschreibung dessen, was ich erreichen möchte, gepostet. – NickW