2014-07-09 17 views
5

Ho un problema molto semplice qui.Impostazione della messa a fuoco E del cursore lampeggiante sulla cella JTable specifica

Quando l'utente fa clic su un pulsante "Modifica" dopo aver selezionato una riga nel mio JTable, il software controlla se questa riga può essere modificata.

Se lo è, vorrei mettere l'attenzione nella prima cella di quella riga con un cursore lampeggiante in modo che l'utente può avviare direttamente digitando nella cella.

Posso impostare correttamente se la riga è modificabile grazie al metodo isEditable() e io uso table.editCellAt(selectedRow, 0) per iniziare la modifica.

Tuttavia

1) No cursore lampeggiante sta comparendo in quella cella

2) L'utente non può digitare nella cella subito (che deve ancora doppio clic sulla cella)

Qualche suggerimento su come ottenere questo?

//////////////////// UPDATE //////////////////////

Anche se il commento di MadProgrammer risolve il problema, risolve solo una parte di esso, ma è perché non sono stato abbastanza preciso.

In effetti, quando eseguo le misure che descrive con un "classico JTable", vale a dire:

table.editCellAt(selectedRow, 0); 
table.setSurrendersFocusOnKeystroke(true); 
table.getEditorComponent().requestFocus(); 

ottengo il cursore lampeggiante e la capacità di digitare subito.

Tuttavia, la parte che mancava è che io do 2 opzioni per l'utente.

1) Può sia selezionare direttamente una riga nella tabella a mano e per questo la soluzione è soddisfacente.

2) Ma ho anche offrire all'utente la possibilità di utilizzare un JTextField per trovare la riga che sta cercando più facilmente. Per questo uso un TableRowSorter con un regexFilter per filtrare le righe visualizzate. E quando provo la soluzione di MadProgrammer (con il filtro attivato) ottengo una java.lang.NullPointerException e non si verificano ulteriori modifiche.

Ecco eccezione:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
at dialogs.DialogEditCouleurs.actionPerformed(DialogEditCouleurs.java:229) 
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) 
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source) 
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source) 
at javax.swing.DefaultButtonModel.setPressed(Unknown Source) 
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source) 
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source) 
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source) 
at java.awt.Component.processMouseEvent(Unknown Source) 
at javax.swing.JComponent.processMouseEvent(Unknown Source) 
at java.awt.Component.processEvent(Unknown Source) 
at java.awt.Container.processEvent(Unknown Source) 
at java.awt.Component.dispatchEventImpl(Unknown Source) 
at java.awt.Container.dispatchEventImpl(Unknown Source) 
at java.awt.Component.dispatchEvent(Unknown Source) 
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) 
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) 
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) 
at java.awt.Container.dispatchEventImpl(Unknown Source) 
at java.awt.Window.dispatchEventImpl(Unknown Source) 
at java.awt.Component.dispatchEvent(Unknown Source) 
at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
at java.awt.EventQueue.access$200(Unknown Source) 
at java.awt.EventQueue$3.run(Unknown Source) 
at java.awt.EventQueue$3.run(Unknown Source) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
at java.awt.EventQueue$4.run(Unknown Source) 
at java.awt.EventQueue$4.run(Unknown Source) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
at java.awt.EventQueue.dispatchEvent(Unknown Source) 
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
at java.awt.WaitDispatchSupport$2.run(Unknown Source) 
at java.awt.WaitDispatchSupport$4.run(Unknown Source) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.awt.WaitDispatchSupport.enter(Unknown Source) 
at java.awt.Dialog.show(Unknown Source) 
at java.awt.Component.show(Unknown Source) 
at java.awt.Component.setVisible(Unknown Source) 
at java.awt.Window.setVisible(Unknown Source) 
at java.awt.Dialog.setVisible(Unknown Source) 
at dialogs.DialogEditCouleurs.<init>(DialogEditCouleurs.java:123) 
at panels.PanelPropertiesEdit.actionPerformed(PanelPropertiesEdit.java:940) 
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) 
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source) 
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source) 
at javax.swing.DefaultButtonModel.setPressed(Unknown Source) 
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source) 
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source) 
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source) 
at java.awt.Component.processMouseEvent(Unknown Source) 
at javax.swing.JComponent.processMouseEvent(Unknown Source) 
at java.awt.Component.processEvent(Unknown Source) 
at java.awt.Container.processEvent(Unknown Source) 
at java.awt.Component.dispatchEventImpl(Unknown Source) 
at java.awt.Container.dispatchEventImpl(Unknown Source) 
at java.awt.Component.dispatchEvent(Unknown Source) 
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) 
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) 
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) 
at java.awt.Container.dispatchEventImpl(Unknown Source) 
at java.awt.Window.dispatchEventImpl(Unknown Source) 
at java.awt.Component.dispatchEvent(Unknown Source) 
at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
at java.awt.EventQueue.access$200(Unknown Source) 
at java.awt.EventQueue$3.run(Unknown Source) 
at java.awt.EventQueue$3.run(Unknown Source) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
at java.awt.EventQueue$4.run(Unknown Source) 
at java.awt.EventQueue$4.run(Unknown Source) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
at java.awt.EventQueue.dispatchEvent(Unknown Source) 
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
at java.awt.EventDispatchThread.run(Unknown Source) 

Qui è la linea che causa l'eccezione:

table.getEditorComponent().requestFocus(); 

Qui è il comportamento reale del software:

1) Nessun filtro: row è selezionato, ma Modifica JButton non è ancora stato cliccato.

enter image description here

2) Nessun filtro: JButton si fa clic su -> previsto comportamento corretto.

enter image description here

Ora il comportamento problematico:

1) e filtri: riga è selezionata, ma Modifica JButton non ancora cliccato. enter image description here

2) e filtri: Modifica JButton cliccato -> nessun cambiamento e l'eccezione sollevata sopra (non preoccupatevi il tooltip)

enter image description here

Ecco la parte rilevante del JDialog:

public class DialogEditColors extends JDialog implements ActionListener, KeyListener 
{ 
final WebNotificationPopup   notificationPopup = new WebNotificationPopup(); 
final TableRowSorter<TableModel> sorter; 
private JTable      tableau = null; 
private EditTableModel    model = null; 
private JPanel      panelBoutons = null; 
private WebTextField    txtFieldSearch = null; 
private JLabel      lblTitle = null; 
private JButton      btnAdd = null, btnDelete = null, btnEdit = null; 
private JButton      btnAnnuler = null, btnSaveCouleur = null; 
private JScrollPane     scroller = null; 
private ColorDao     colorDao = new ColorDao(Share.connection); 

public DialogEditColors() 
    { 
     super(); 
     setSize(439, 313); 
     setTitle(" Edition couleurs"); 
     getContentPane().setLayout(null); 
     setModal(true); 
     setResizable(false); 
     setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 
     setLocationRelativeTo(null); 

     btnSaveCouleur = new JButton("Enregistrer"); 
     btnSaveCouleur.setBounds(317, 247, 89, 26); 
     btnSaveCouleur.addActionListener(this); 

     btnAnnuler = new JButton("Annuler"); 
     btnAnnuler.setBounds(214, 247, 89, 26); 
     btnAnnuler.addActionListener(this); 

     btnAdd = new JButton(""); 
     btnAdd.setBounds(new Rectangle(10, 8, 33, 26)); 
     btnAdd.addActionListener(this); 

     btnDelete = new JButton(""); 
     btnDelete.setBounds(new Rectangle(53, 8, 33, 26)); 
     btnDelete.addActionListener(this); 

     btnEdit = new JButton(""); 
     btnEdit.setBounds(new Rectangle(96, 8, 33, 26)); 
     btnEdit.addActionListener(this); 

     panelBoutons = new JPanel(); 
     panelBoutons.setBorder(new LineBorder(Color.GRAY)); 
     panelBoutons.setBounds(27, 11, 378, 43); 
     panelBoutons.setLayout(null); 

     txtFieldSearch = new WebTextField("", 10); 
     txtFieldSearch.setBounds(193, 9, 175, 24); 
     panelBoutons.add(txtFieldSearch); 
     txtFieldSearch.setTrailingComponent(new WebImage(IconUtil.createIcon("/images/search.png").getImage())); 
     txtFieldSearch.addKeyListener(this); 

     Object[][] data = new Object[colorDao.findAll().size()][2]; 
     String[] title = { "Couleur", "Description" }; 

     int i = 0; 
     for (Couleur coul : colorsDao.findAll()) 
      { 
       data[i][0] = coul.getNom(); 
       data[i][1] = coul.getDescription(); 
       i++; 
      } 

     model = new EditTableModel(data, title); 
     tableau = new JTable(model) 
     {//COLORING THE BACKGROUND IN ALTERNATE COLORS 
      public Component prepareRenderer(TableCellRenderer renderer, int row, int column) 
       { 
        Component returnComp = super.prepareRenderer(renderer, row, column); 
        Color alternateColor = new Color(242, 242, 242); 
        Color whiteColor = Color.WHITE; 
        if (!returnComp.getBackground().equals(getSelectionBackground())) 
         { 
          Color bg = (row % 2 == 0 ? alternateColor : whiteColor); 
          returnComp.setBackground(bg); 
          bg = null; 
         } 
        return returnComp; 
       }; 
     }; 

     tableau.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
     tableau.setCellSelectionEnabled(true); 
     sorter = new TableRowSorter<TableModel>(model); 
     tableau.setRowSorter(sorter); 
     sorter.addRowSorterListener(tableau); 

     scroller = new JScrollPane(tableau); 
     scroller.setBounds(27, 65, 378, 171); 
     addComponents(); 
     setVisible(true); 
    }//END OF CONSTRUCTOR 

private void addComponents() 
    { 
     getContentPane().add(scroller); 
     getContentPane().add(btnSaveCouleur); 
     getContentPane().add(btnAnnuler); 
     panelBoutons.add(btnAdd); 
     panelBoutons.add(btnDelete); 
     panelBoutons.add(btnEdit); 
     getContentPane().add(panelBoutons); 
    }//END OF METHOD 

public void actionPerformed(ActionEvent e) 
    { 
    if (e.getSource() == btnEdit) 
      { 
       int selectedRow = 0; 
       if (tableau.getSelectedRowCount() != 0) //THERE IS A CHOSEN COLOR IN JTABLE 
        { 
         String selectedColor = (tableau.getValueAt(tableau.getSelectedRow(), tableau.getSelectedColumn())) 
           .toString(); 
         //WE'RE TESTING IF THE COLOR IS READONLY 
         if (colorDao.findByName(selectedColor).get(0).getReadOnly() == true) 
          {//IF THE COLOR IS READONLY 
           notificationPopup.setIcon(NotificationIcon.error); 
           notificationPopup.setContent("This item is readonly : impossible to edit it !"); 
           NotificationManager.showNotification(notificationPopup); 
          } 

         else 
          {////THE COLOR IS NOT READONLY --> EDITING IS ALLOWED 
           //1) NOTIFY THE MODEL THAT EDITING IS ALLOWED 
           model.setEditingValidated(true); 
           //2) TEST WETHER FILTER IS ACTIVE OR NOT TO SEE IF INDEX CONVERSION IS NEEDED 
           if (txtFieldSearch.getText() == "") 
            {//NO FILTER 
             selectedRow = tableau.getSelectedRow(); 
            } 
           else 
            {//FILTER IS ACTIVE 
             int modelIndex = tableau.convertRowIndexToModel(tableau.getSelectedRow()); 
             selectedRow = modelIndex; 
            } 

           model.setEditingValidatedRowNb(selectedRow); 
           tableau.editCellAt(selectedRow, 0); 
           tableau.setSurrendersFocusOnKeystroke(true); 
           tableau.getEditorComponent().requestFocus(); 
          } 
        } 
       else 
        { //NO CHOSEN COLOR 
         notificationPopup.setIcon(NotificationIcon.error); 
         notificationPopup.setContent("No chosen color !"); 
         NotificationManager.showNotification(notificationPopup); 
        } 
      } 

     else if (e.getSource() == btnAnnuler) 
      {//WE LEAVE THE DIALOG WITHOUT DOING ANYTHING 
       Share.chosenColor = null; 
       this.dispose(); 
      } 
    }//END OF METHOD 

public void keyReleased(KeyEvent e) 
    { 
     if (e.getSource() == txtFieldSearch) 
      { 
       String text = txtFieldSearch.getText(); 
       if (text.length() == 0) 
        { 
         sorter.setRowFilter(null); 
        } 
       else 
        { 
         sorter.setRowFilter(RowFilter.regexFilter("(?i)" + text)); 
        } 
       ((AbstractTableModel) tableau.getModel()).fireTableDataChanged(); 
      } 
    }//END OF METHOD 
}//END OF CLASS 

E qui è la parte rilevante del TableModel:

public class EditTableModel extends AbstractTableModel implements Serializable 
{ 
protected Vector dataVector; 
protected Vector columnIdentifiers; 
protected boolean isEditingValidated  = false; 
protected int  editingValidatedRowNb = 0; 

public boolean isCellEditable(int row, int column) 
    { 
     //IF EDITING IS NOT VALIDATED NOTHING IS EDITABLE/RETURN FALSE 
     if (!isEditingValidated) 
      { 
       return false; 
      } 
     //ELSE A FURTHER TEST IS NEEDED TO DECIDE 
     else 
      { 
       //IF THE CURRENT ROW IS THE ROW FOR WHICH EDITING IS VALIDATED RETURN TRUE 
       if (row == editingValidatedRowNb) 
        { 
         return true; 
        } 
       //ELSE THE ROW IS ANOTHER ROW SO RETURN FALSE 
       else 
        { 
         return false; 
        } 
      } 
    }//END OF METHOD 
}//END OF CLASS 

suggerimenti qualcuno?

+1

due cose. Prova a impostare ['SurrendersFocusOnKeystroke'] (http://docs.oracle.com/javase/7/docs/api/javax/swing/JTable.html # getSurrendersFocusOnKeystroke()) proprietà del 'JTable' e assicurarsi che l'editor abbia effettivamente lo stato attivo – MadProgrammer

+0

Perfect MadProgrammer, questo funziona! Nel caso in cui qualcun altro necessiti delle specifiche, sono riuscito a ottenere ciò con il seguente codice: table.editCellAt (selectedRow, 0); \t \t \t \t \t \t \t \t \t table.setSurrendersFocusOnKeystroke (true); \t \t \t \t \t \t \t \t \t table.getEditorComponent() requestFocus().; Grazie mille !! – Zek101

+2

È possibile [rispondere alla propria domanda] (http://meta.stackoverflow.com/q/17463/163188). – trashgod

risposta

0

Per la seconda parte del problema, ho risolto come segue:

In primo luogo ho usato il

table.setCellSelectionEnabled(true); 

Giusto per fare in modo che la selezione di una particolare cella in una JTable è abilitato.

Poi, ho usato

table.changeSelection(int row, int column, false, false); 

I due valori booleani sopra sono ginocchiera ed estendere rispettivamente. false, false qui cancellerà la selezione precedente e assicurerà che la nuova cella sia selezionata.

il frammento di cui sopra è stato utilizzato per selezionare quella particolare cella nella tabella. L'ho fatto, in modo tale che quando uso il metodo editCellAt(), sicuramente lo scatto inizia a modificare la cella attualmente selezionata.

Se per qualsiasi motivo editCellAt() non funziona correttamente, si otterrà null da getEditorComponent(). Dal momento che nessun componente è attualmente in fase di modifica, il problema è .

table.getEditorComponent() 

Poi per avviare la modifica della cella ho usato

table.editCellAt(int row, int column); 

questo è stato utilizzato per avviare la modifica della componente cellulare di programmazione.

e, infine, per ottenere il cursore lampeggiante/focus su quella particolare cella ho usato

table().getEditorComponent().requestFocus(); 

Spero che questo aiuti. Funziona come un fascino per me. Fammi sapere se non è così.

In breve, ho aggiunto seguenti righe di codice:

table.setCellSelectionEnabled(true); 
table.changeSelection(int row, int column, false, false); 
table.editCellAt(int row, int column); 
table().getEditorComponent().requestFocus();