2017-10-10 7 views
1

私は現在、これは、TableModel内で関連する方法であるのTableModel setCellEditableと自動的にバック

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

を使用して編集するためのセルのロック解除を可能にする私のJTableでのPopupMenuを実装しようとしているに値を設定します

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()次いでeditableCells [] []配列の値を返します。 しかし、私のコードでは、フォーカスを失ったときに編集不可能なセルに戻す必要がありますか?

若干関連した注記では、セルにすぐに注目するようにしたいと思います。私はgetEditorComponent().requestFocus()について読んだことがあります。しかし、その時点では何も編集されていないので、セルは選択されていません(そして、そのメソッドを使用すると、私の思考プロセスをサポートするように見えるnullpointerexceptionがスローされます)。

誰でも正しい方向に私を指摘できますか?私はどこが間違っているのか分かりません。おかげ

**編集:

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

      } 
     }); 
    } 
} 

が、それはどちらか動作するように見えていないが、私はおそらく実装しています:フォーカスが私はのFocusListenerでカスタムのCellRendererを追加しようとした失われたときにセルをロックしますそれは間違って(私はレンダラが追加されたことをチェックしましたが)


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()); 
     } 
    } 
} 

とのTableModelとデータクラス:長さ

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; } 
} 

謝罪 - 私は、おそらく悪い私が達成したいものを再作成しなくても、それを短くする方法を知りませんでした。このコードでは、右クリックして「Unlock」をクリックすると既に行を左クリックしていなければなりません。それ以外の場合は、arrayIndexOutOfBounds例外になります。私はまだ正確な原因を見つけることができませんでした。

しかし、基本的に右クリックしてロック解除を選択すると、カーソルがセルに表示されます。現時点では、ロック解除をクリックし、セルをダブルクリックする必要があります。

+0

レンダラは実際のコンポーネントではありません。これは単にコンポーネントのイメージをペイントするために使用されます。それは決して焦点を得ることはありません。 "=="を使用して文字列を比較しないでください。 'equals(...)'メソッドを使います。問題を示す適切な[mcve]を投稿してください。 – camickr

+0

申し訳ありませんが、それほど簡単なことではありませんが、私が達成しようとしていることの説明付きで完全に動作する例を投稿しました。ありがとう。 – NickW

答えて

0

ただし、フォーカスが失われたときに私のコードでセルを編集不可能に変更する必要がありますか? -

あなた可能性:

  1. オーバーライドデータが変更されると、セルは編集できないようにするあなたのTableModelのsetValueAt(...)方法。

  2. 使用TableModelListenerセルのデータが更新されるとイベントを生成します。

+0

ありがとう。それをsetValueAt()に入れると、完璧に動作します。 setCellEditable()はfireTableCellUpdated()を呼び出しますが、無限ループなしではそこに置くことはできませんが、SSCCEがなければコメントすることはできません。どちらにしても今は働いているので、もう一度感謝します。 – NickW

+0

私はこれをマークした直前に、セルをすぐに編集可能にするにはどうすればよいでしょうか?つまり、セルを右クリックして[ロック解除]を選択すると、カーソルがそこにあります。後でもう一度ダブルクリックする必要はありません。 SSCCEを作ることができれば助かりますが、私を指す漠然とした方向性を持っていても役立つでしょう。 – NickW

+0

@NickW、 'setCellEditable()はfireTableCellUpdated()を呼び出します。' - セル内のデータが変更されていないので、fireXXX()メソッドを呼び出すべきではありません。 – camickr