2014-05-23 16 views
2

4 개의 열이있는 jtable을 갖고 싶습니다. 하나의 열은 콤보 박스 여야합니다. 다른 열은 문자열입니다.Jtable jcombobox 및 셀 편집

셀에서 한 번 클릭하면 셀이 깜박이는 caret/cursor.Also와 함께 편집 가능한 상태가되고 싶습니다. 콤보 상자를 클릭하면 combox 세트 팝업 표시가 나타납니다.

자습서 "How to Use Tables"를 읽었으며 셀의 콤보 박스를 한 번만 클릭하면 열립니다. 내 첫 번째 문제는 우리가 추상 테이블 모델을 구현하고 DefaultTableModel을 사용하지 않을 때 자습서의 코드가 작동하는 이유를 이해할 수 없다는 것입니다.

내 코드는 다음과 같습니다

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.Dimension; 
import javax.swing.DefaultCellEditor; 
import javax.swing.DefaultComboBoxModel; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTabbedPane; 
import javax.swing.JTable; 
import javax.swing.JTextField; 
import javax.swing.SwingUtilities; 
import javax.swing.event.CellEditorListener; 
import javax.swing.event.ChangeEvent; 
import javax.swing.table.AbstractTableModel; 
import javax.swing.table.DefaultTableCellRenderer; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.TableColumn; 

public class JtabletestOK { 

    public static void main(String[] args) { 

     JtabletestOK test = new JtabletestOK(); 
     test.go(); 
    } 

    public void go() { 

     //create the frame 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 



     //create a table and add it to a scroll pane in a new tab 
     JTable jTable1 = new JTable() 
     { 
      // Place cell in edit mode when it 'gains focus' 

      public void changeSelection(
        int row, int column, boolean toggle, boolean extend) 
      { 
       super.changeSelection(row, column, toggle, extend); 

       if (editCellAt(row, column)) 
       { 
        Component editor = getEditorComponent(); 
        editor.requestFocusInWindow(); 
        // System.out.println("ffin focus gagne"); 
        if (editor instanceof JTextField) { 

         JTextField jf = (JTextField) editor; 
         jf.select(0, jf.toString().length()); 
        }} 
      } 
     }; 


     jTable1.setPreferredScrollableViewportSize(new Dimension(800,100)); 
     jTable1.setFillsViewportHeight(true); 

     //Create the scroll pane and add the table to it. 
     JScrollPane scrollPane = new JScrollPane(jTable1); 

     Object columnNames[] = { "DataCombo", "Data 2", "Data 3", "Data 4" }; 
     DefaultTableModel model = new DefaultTableModel(columnNames, 0); 

     Object rowData[] = { "", "Row1-Column2", "Row1-Column3", "Row1-Column3" }; 
     model.addRow(rowData); 
     jTable1.setModel(model); 


     String[] comboBoxArray = {"proem1","veitem2","atem3"}; 
     JComboBox jcb = new JComboBox(comboBoxArray); 
     jcb.setEditable(true); 


     TableColumn colCombo = jTable1.getColumnModel().getColumn(0); 
     colCombo.setCellEditor(new DefaultCellEditor(jcb)); 

     jcb.setEditable(true); 



     frame.getContentPane().add(scrollPane); 
     frame.pack(); 
     frame.setVisible(true); 

    } 

추상 모델과 소스는 여기에 있습니다 : http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableRenderDemoProject/src/components/TableRenderDemo.java

그냥 문제를 찾을 : 문 (참) jcb.setEditable을 주석 때, comboxcell을 한 번 클릭하면 셀이 열립니다. 하지만 왜 더 잘 작동하는지 모르겠습니다. 또한, 나는 combox 편집 할 싶습니다.

어떻게 다른 셀에서도 동일한 동작을 수행 할 수 있습니다.

안녕하세요 다시, 내가 을하기 위해 코드를 업데이트 한

- 편집 될 콤보 내가 방법을 재정 의하여 셀을 한 번 클릭하면 - 내가 방법 를 재정 의하여 셀을 한 번 클릭하면 세포가 편집 될 내가 콤보 상자를 클릭하면

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import javax.swing.AbstractAction; 
import javax.swing.AbstractCellEditor; 
import javax.swing.Action; 
import javax.swing.ActionMap; 
import javax.swing.DefaultCellEditor; 
import javax.swing.DefaultComboBoxModel; 
import javax.swing.InputMap; 
import javax.swing.JComboBox; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTabbedPane; 
import javax.swing.JTable; 
import javax.swing.JTextField; 
import javax.swing.KeyStroke; 
import javax.swing.SwingUtilities; 
import javax.swing.event.CellEditorListener; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.PopupMenuEvent; 
import javax.swing.event.PopupMenuListener; 
import javax.swing.table.AbstractTableModel; 
import javax.swing.table.DefaultTableCellRenderer; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.TableCellEditor; 
import javax.swing.table.TableColumn; 
import javax.swing.text.JTextComponent; 

public class JtabletestOK { 

    public static void main(String[] args) { 

     JtabletestOK test = new JtabletestOK(); 
     test.go(); 
    } 

    public void go() { 

     //create the frame 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 



     //create a table and add it to a scroll pane in a new tab 
     JTable jTable1 = new JTable() 

     { 
      // Place cell in edit mode when it 'gains focus' 

      public void changeSelection(
        int row, int column, boolean toggle, boolean extend) 
      { 
       super.changeSelection(row, column, toggle, extend); 

       if (column > 0) 
       { 

        if (editCellAt(row, column)) 
        { 
         Component editor = getEditorComponent(); 
         editor.requestFocusInWindow(); 
         // System.out.println("ffin focus gagne"); 
         if (editor instanceof JTextField) { 

          JTextField jf = (JTextField) editor; 
          jf.select(0, jf.toString().length()); 
         }} 
       } 
      } 
     }; 



     jTable1.setPreferredScrollableViewportSize(new Dimension(800,100)); 
     jTable1.setFillsViewportHeight(true); 
     replaceTabByEnter(jTable1); 

     //Create the scroll pane and add the table to it. 
     JScrollPane scrollPane = new JScrollPane(jTable1); 

     Object columnNames[] = { "DataCombo", "Data 2", "Data 3", "Data 4" }; 
     DefaultTableModel model = new DefaultTableModel(columnNames, 0); 

     Object rowData[] = { "", "Row1-Column2", "Row1-Column3", "Row1-Column3" }; 
     model.addRow(rowData); 
     jTable1.setModel(model); 


     String[] comboBoxArray = {"proem1","veitem2","atem3"}; 
     JComboBox jca = new JComboBox(comboBoxArray); 
     jca.setSelectedItem(""); 
     JTextComponent editor = (JTextComponent) jca.getEditor().getEditorComponent(); 

     jca.addPopupMenuListener(new PopupMenuListener() { 

      @Override 
      public void popupMenuWillBecomeVisible(PopupMenuEvent e) { 
       JComponent ja = (JComponent) e.getSource(); 
      } 

      @Override 
      public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { 
       JComponent ja = (JComponent) e.getSource(); 
       JTable jtb = (JTable) ja.getParent(); 
       jtb.changeSelection(0,1,false,false); 
      } 

      @Override 
      public void popupMenuCanceled(PopupMenuEvent e) { 
      } 
     }); 



     editor.addMouseListener(new MouseListener() { 

      @Override 
      public void mouseClicked(MouseEvent e) { 
       System.out.println("Not mouseClicked yet."); 
      } 

      @Override 
      public void mousePressed(MouseEvent e) { 
       System.out.println("Not mousePressed yet."); 
      } 

      @Override 
      public void mouseReleased(MouseEvent e) { 
       JComponent ja = (JComponent) e.getSource(); 
       JComponent jcbloc = (JComponent) ja.getParent(); 
       JComboBox jcb = (JComboBox) jcbloc; 
       jcb.setPopupVisible(true); 
       System.out.println("Not mouseReleased yet."); 

      } 

      @Override 
      public void mouseEntered(MouseEvent e) { 
       System.out.println("Not mouseEntered yet."); 
      } 

      @Override 
      public void mouseExited(MouseEvent e) { 
       System.out.println("Not mouseExited yet."); 
      } 
     }); 

     autocompletecombo jcb =new autocompletecombo(jca); 
     TableColumn colCombo = jTable1.getColumnModel().getColumn(0); 
     jca.setEditable(true); 
     comboboxEditor cbe = new comboboxEditor(jca); 
     colCombo.setCellEditor(cbe); 

     frame.getContentPane().add(scrollPane); 
     frame.pack(); 
     frame.setVisible(true); 

    } 


    public void replaceTabByEnter(JTable jtane) { 

     KeyStroke tab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0); 
     KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0); 
     InputMap im = jtane.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 
     im.put(enter, im.get(tab)); 
    } 


    class comboboxEditor extends AbstractCellEditor implements TableCellEditor{ 

     JComboBox comboBox; 
     JTextField jtf; 

     S11InitialSelection sjcb; 
     @Override 
     public Object getCellEditorValue() { 
      return comboBox.getSelectedItem(); 
     } 

     public comboboxEditor(JComboBox jcb) { 

      comboBox = jcb; 
      jtf.selectAll(); 
     } 

     @Override 
     public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 

      comboBox.setSelectedItem(value); 
      return comboBox; 
     } 

     public boolean stopCellEditing() { 


      fireEditingStopped(); 
      //  jt.EditNextCell(); 
      return true; 

     } 


    } 










} 
  • 내가 그것을 선택하여 텍스트를 강조하고 싶습니다 :

    나는, 그것은 다른 도움이 될 수 있습니다 여기에 나의 새로운 코드를 삽입. selectAll() 메서드 또는 이와 유사한 것을 사용하기 위해 jcombobox에서 텍스트 필드를 얻는 방법을 기억하지 못합니다. 당신의 도움에 대한

      public void mouseReleased(MouseEvent e) { 
           JComponent ja = (JComponent) e.getSource(); 
           JComponent jcbloc = (JComponent) ja.getParent(); 
           JComboBox jcb = (JComboBox) jcbloc; 
           jcb.setPopupVisible(true); 
           JTextComponent editor = (JTextComponent) jcb.getEditor().getEditorComponent(); 
           editor.setSelectionStart(0); 
           editor.setSelectionEnd(editor.getText().length()); 
           System.out.println("Not mouseReleased yet."); 
    
          } 
    

    감사 :

은 내가 그것에 대해 해결책을 찾을 수 있습니다.

+0

AbstractTableModel을 사용하여 예제를 볼 수 있습니까? –

답변

1

마침내 모든 문제를 해결하는 방법을 찾았습니다. 나는 모든 코드를 게시한다. 다른 사람들에게 도움이되기를 바랍니다. 문제를 해결할 더 좋은 방법을 찾으면 나는 열려 있습니다.

그것은 두 가지 이상한 일이 남아 있지만, 내가 원하는대로 작동, 그래서 아이디어로 somenone가있는 경우 : 내가 코드를 이동하는 경우

  •  if(e.getKeyChar() == KeyEvent.VK_ENTER){ 
          JComponent ja = (JComponent) e.getSource(); 
          JComboBox jcbloc = (JComboBox) ja.getParent(); 
          JTable jtb = (JTable) jcbloc.getParent(); 
          jtb.changeSelection(0,1,false,false); 
         } 
    

에가의 keyPressed 대신의 keyReleased , 작동하지 않습니다.

  • 기본 셀 텍스트에서 Enter 키를 누르면 프로그램이 다음 셀로 이동합니다. Enter 키를 누른 채로 다음 셀로 어떻게 혼자가는 지 이해할 수 없습니다. 여기

모든 코드 : 당신의 도움에 대한

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.awt.event.FocusEvent; 
import java.awt.event.FocusListener; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import javax.swing.AbstractAction; 
import javax.swing.AbstractCellEditor; 
import javax.swing.Action; 
import javax.swing.ActionMap; 
import javax.swing.DefaultCellEditor; 
import javax.swing.DefaultComboBoxModel; 
import javax.swing.InputMap; 
import javax.swing.JComboBox; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTabbedPane; 
import javax.swing.JTable; 
import javax.swing.JTextField; 
import javax.swing.KeyStroke; 
import javax.swing.SwingUtilities; 
import javax.swing.event.CellEditorListener; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.PopupMenuEvent; 
import javax.swing.event.PopupMenuListener; 
import javax.swing.plaf.basic.BasicTextUI; 
import javax.swing.table.AbstractTableModel; 
import javax.swing.table.DefaultTableCellRenderer; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.TableCellEditor; 
import javax.swing.table.TableColumn; 
import javax.swing.text.JTextComponent; 


public class JtabletestOKStackOver { 

public static void main(String[] args) { 

    JtabletestOKStackOver test = new JtabletestOKStackOver(); 
    test.go(); 
} 

public void go() { 

    //create the frame 
    JFrame frame = new JFrame(); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    //create a table and add it to a scroll pane in a new tab 
    JTable jTable1 = new JTable() 

    { 
     // Place cell in edit mode when it 'gains focus' 

     public void changeSelection(
       int row, int column, boolean toggle, boolean extend) 
     { 
      super.changeSelection(row, column, toggle, extend); 


      if (column > -1) 
      { 

       if (editCellAt(row, column)) 
       { 
        Component editor = getEditorComponent(); 
        editor.requestFocusInWindow(); 
        if (editor instanceof JTextField) { 

         JTextField jf = (JTextField) editor; 
         jf.select(0, jf.toString().length()); 
        } 
        if (editor instanceof JComboBox) { 
         JComboBox jcb = (JComboBox) editor; 
         jcb.setPopupVisible(true); 
         JTextComponent editorCombo = (JTextComponent) jcb.getEditor().getEditorComponent(); 
         editorCombo.setSelectionStart(0); 
         editorCombo.setSelectionEnd(editorCombo.getText().length()); 
        } 



       } 
      } 
     } 
    }; 





    jTable1.setPreferredScrollableViewportSize(new Dimension(800,100)); 
    jTable1.setFillsViewportHeight(true); 
    jTable1.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); 

    //Create the scroll pane and add the table to it. 
    JScrollPane scrollPane = new JScrollPane(jTable1); 

    Object columnNames[] = { "DataCombo", "Data 2", "Data 3", "Data 4" }; 
    DefaultTableModel model = new DefaultTableModel(columnNames, 0); 

    Object rowData[] = { "", "Row1-Column2", "Row1-Column3", "Row1-Column3" }; 
    model.addRow(rowData); 
    jTable1.setModel(model); 


    String[] comboBoxArray = {"proem1","veitem2","atem3"}; 
    JComboBox jca = new JComboBox(comboBoxArray); 
    jca.setSelectedItem(""); 
    JTextComponent editor = (JTextComponent) jca.getEditor().getEditorComponent(); 

    editor.addKeyListener(new KeyListener() { 

     @Override 
     public void keyTyped(KeyEvent e) { 
     } 

     @Override 
     public void keyPressed(KeyEvent e) { 
      if(e.getKeyChar() == KeyEvent.VK_ENTER){ 
       JComponent ja = (JComponent) e.getSource(); 
       JComboBox jcbloc = (JComboBox) ja.getParent(); 
       JTable jtb = (JTable) jcbloc.getParent(); 
       jtb.changeSelection(0,1,false,false); 
      } 
     } 

     @Override 
     public void keyReleased(KeyEvent e) { 

     } 
    }); 


    editor.addFocusListener(new FocusListener() { 

     @Override 
     public void focusGained(FocusEvent e) { 
      JComponent ja = (JComponent) e.getSource(); 
      JComponent jcbloc = (JComponent) ja.getParent(); 
      JComboBox jcb = (JComboBox) jcbloc; 
      jcb.setPopupVisible(true); 
      JTextComponent editor = (JTextComponent) jcb.getEditor().getEditorComponent(); 
      editor.setSelectionStart(0); 
      editor.setSelectionEnd(editor.getText().length()); 
     } 

     @Override 
     public void focusLost(FocusEvent e) { 
     } 
    }); 





    TableColumn colCombo = jTable1.getColumnModel().getColumn(0); 
    jca.setEditable(true); 
    comboboxEditor cbe = new comboboxEditor(jca); 
    colCombo.setCellEditor(cbe); 


    TableColumn colAutre = jTable1.getColumnModel().getColumn(1); 
    TableColumn colAutre2 = jTable1.getColumnModel().getColumn(2); 
    TableColumn colAutre3 = jTable1.getColumnModel().getColumn(3); 
    textCellEditor dce = new textCellEditor(new JTextField()); 

    colAutre.setCellEditor(dce); 
    colAutre2.setCellEditor(dce); 
    colAutre3.setCellEditor(dce); 



    frame.getContentPane().add(scrollPane); 
    frame.pack(); 
    frame.setVisible(true); 

} 







class comboboxEditor extends AbstractCellEditor implements TableCellEditor{ 

    JComboBox comboBox; 



    public comboboxEditor(JComboBox jcb) { 

     comboBox = jcb; 
    } 


    public Object getCellEditorValue() { 
     return comboBox.getSelectedItem(); 
    } 


    @Override 
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 

     comboBox.setSelectedItem(value); 
     return comboBox; 
    } 

    public boolean stopCellEditing() { 
     fireEditingStopped(); 
     return true; 

    } 


} 

class textCellEditor extends AbstractCellEditor implements TableCellEditor{ 
    JTextField jtextfield; 

    public textCellEditor(JTextField jtf) { 
     jtextfield = jtf; 
    } 


    public Object getCellEditorValue() { 
     return jtextfield.getText(); 
    } 


    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 
     if (isSelected) { 
      // cell (and perhaps other cells) are selected 
     } 
     if (value== null) 
     { 
      value=""; 
     } 
     value = value.toString(); 
     if (value instanceof Integer) { 
      value = value.toString(); 
     } 
     jtextfield.setText((String) value); 

     // Return the configured component 
     return jtextfield; 
    } 

    public boolean stopCellEditing() { 
     fireEditingStopped(); 
     return true; 

    } 

} 



} 

감사합니다.

-1

AbstractTableModel을 사용하는 코드가 왜 작동하지 않는지 알 수 없습니다 (볼 수 없기 때문에). 그러나 나는 당신이 당신의 모범을 보이도록 도와 줄 수 있습니다.

jcb.addActionListener(new java.awt.event.ActionListener() { 
     public void actionPerformed(java.awt.event.ActionEvent evt) { 
      System.out.println("test"); 
      final JComboBox j= (JComboBox)evt.getSource(); 
      SwingUtilities.invokeLater(new Runnable() { 

       @Override 
       public void run() { 
        if (j.isDisplayable()) j.setPopupVisible(true); 
       } 
      }); 

     }}); 
+0

샘플 작업! SwingUtilities.invokeLater와의 차이점을 설명해 주시겠습니까? 나중에 호출하지 않아도 작동하지 않는 이유는 무엇입니까? – nick

+0

아마도 콤보 상자 편집기가 포커스를 얻으면 팝업이 자동으로 닫힙니다. 그래서 우리는 그것을 즉시 열어 봐야합니다. invokeLater가 도움이 될 수 있습니다. 하지만 내 설명이 맞는지 확실하지 않습니다. –

+0

-1, 콤보 상자 팝업을 표시하는 데 ActionListener를 사용하지 마십시오. 이것은 편집자가 처리합니다. – camickr

0

콤보 상자에서 ActionListener를 사용하지 마십시오. 편집기에서 셀을 클릭하면 "팝업"이 표시됩니다.

내 첫 번째 문제는 왜 우리가 추상 테이블 모델을 구현하고 DefaultTableModel을 작동하지 않을 때 자습서의 코드가 작동하는지 이해할 수 없다는 것입니다.

편집은 TableModel isCellEditable(...) 메서드에 의해 제어됩니다. 편집 가능한 셀을 클릭하면 (자), JTable는 적절한 에디터를 사용합니다. 편집기가 콤보 상자이면 셀을 클릭하면 팝업이 표시됩니다.

그냥 문제를 찾으십시오 : jcb.setEditable (true) 문을 주석 처리 할 때; comboxcell을 한 번 클릭하면 셀이 열립니다. 하지만 왜 더 잘 작동하는지 모르겠다.

셀을 클릭하면 MouseEvent가 편집기 (예 : 콤보 상자)로 전달된다고 생각합니다. 콤보 상자가 편집 가능하기 때문에 MouseEvent는 텍스트 필드로 이동하므로 텍스트 필드의 포커스는 그대로 유지되고 팝업은 표시되지 않습니다. 이것을 JTable에 표시되지 않는 통상의 combobox로 시도해, 같은 동작을 봅니다.

+0

당신은 무슨 질문에 대답하려고합니까 ??? DefaultTableModel은 항상 isCellEditable()에 대해 true를 반환합니다. –

+0

콤보 상자 드롭 다운을 표시하기 위해 특별한 작업을 수행 할 필요가 없다는 것을 OP에 알리려고합니다. 셀을 편집 할 수 있으면 테이블에서 적절한 편집기를 선택합니다. 업데이트되었습니다. – camickr

+0

네 말이 맞아. 나는 기본 콤보 박스와 동일한 동작을한다. 액션 리스너를 제거했습니다. 콤보 드롭 다운 목록을 여는 방법에 대해 아이디어를 얻었습니까? 즉, 콤보에서 팝업을 표시하기 위해 텍스트 필드에 리스너를 넣어야합니까? – nick