Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
Java - Jtable editabile con celle JtextField - problemi di Focus con altri componenti
Forum - Java - Jtable editabile con celle JtextField - problemi di Focus con altri componenti

Avatar
PaoloDaPrato (Normal User)
Newbie


Messaggi: 2
Iscritto: 16/03/2020

Segnala al moderatore
Postato alle 16:36
Lunedì, 16/03/2020
Buongiorno a tutti, sono nuovo del forum.
Spero qualcuno di voi possa darmi una mano su un problema che mi porto dietro da tempo e di cui non riesco a trovare soluzione ammesso che alla fine non sia un bug di java...
Spiego il progetto Java:

Il problema risiede nell'interfaccia che è composta da:
- JInternalFrame con all'interno
- JTabbedPane con all'interno
- Componenti quali JtextField, JPanel con all'interno JTable, ComboBox etc
Lo spostamento da un componente all'altro, usando la tastiera, è gestito da una classe FocusTraversalPolicy legata al JTabbedPane;
in questa classe si gestisce l'avanzamento di componente in componente con i tasti TAB e ShiftTAB;
tutto funziona meravigliosamente pure nel caso di componente Jtable se non si è ancora in Edit di cella.
Preciso che al componente Jtable ho disattivato i tasti Tab e ShiftTAB perchè non siano utilizzati per movimenti tra celle e possono essere utilizzati per passaggio da JTable a componente successivo o precedente al JTable stesso.

Queste le istruzioni che disattivano i 2 tasti come spostamento celle nel JTable

Codice sorgente - presumibilmente Java

  1. ActionMap myTableActionMap = myTable.getActionMap();
  2. myTableActionMap.put("selectPreviousColumnCell", new myPreviousFocusHandler());
  3. myTableActionMap.put("selectNextColumnCell", new myNextFocusHandler());
  4. public class myPreviousFocusHandler extends AbstractAction
  5. {
  6. public void actionPerformed(ActionEvent evt)
  7. {
  8. KeyboardFocusManager myManager = KeyboardFocusManager.getCurrentKeyboardFocusManage r();
  9. myManager.focusPreviousComponent();
  10. }
  11. }
  12. public class myNextFocusHandler extends AbstractAction
  13. {
  14. public void actionPerformed(ActionEvent evt)
  15. {
  16. KeyboardFocusManager myManager = KeyboardFocusManager.getCurrentKeyboardFocusManage r();
  17. myManager.focusNextComponent();
  18. }
  19. }



Il problema che vado a descrivere si manifesta solo quando sono in edit di cella del JTable (componente JTextField) e premo il tasto ShiftTab.
Nel caso sopradescritto non si comporta come mi aspetterei e soprattutto si comporta in modo diverso rispetto a come si comporta avendo premuto il tasto TAB.

Nel caso di edit di cella (JTextField) nel JTable se si preme il tasto TAB il programma si comporta come è nelle mie attese:
- Passa il controllo al FocusTraversalPolicy del JtabbedPane
- Passa da StopCellEditing della cella in edit
- Passa da getCellEditorValue della cella in edit
- Per debug passa pure da un FocusLost di un Listener sulla JTable dove si rileva che il prossimo componente è quello corretto a cui passa effettivamente il focus
- Attiva il focus sul componente successivo

Nel caso di edit di cella (JTextField) nel JTable se si preme il tasto ShiftTAB il programma si comporta come non è nelle mie attese e diversamente dal tasto TAB:
- NON Passa il controllo al FocusTraversalPolicy del JtabbedPane
- NON Passa da StopCellEditing della cella in edit
- NON Passa da getCellEditorValue della cella in edit
- Passa invece da FocusLost di un Listener sulla JTable dove si rileva che il prossimo componente è lo stesso JTextField che gestisce l'edit di cella.
- Rimane attiva la stessa cella della JTable in uno stato non si capisce se di edit o meno.

Spero di essere stato chiaro
L'intero sorgente è troppo esteso per poter essere pubblicato ma non ho problemi a riportarne i pezzi che possono interessare la discussione.

Ultima modifica effettuata da PaoloDaPrato il 16/03/2020 alle 16:38
PM Quote
Avatar
PaoloDaPrato (Normal User)
Newbie


Messaggi: 2
Iscritto: 16/03/2020

Segnala al moderatore
Postato alle 8:11
Martedì, 24/03/2020
Buongiorno
Ripropongo un estratto del problema che ho esposto nel primo post sperando che con un esempio pratico qualcuno mi possa dare una mano

Facendo girare l'esempio (trascurato ma funzionale a dimostrare il mio problema) si notano in console i passaggi nel focustraversalpolicy

Prova1: si preme semplicemente TAB o ShiftTab
In console si vedono i passaggi nei metodi getComponentAfter e getComponentBefore; in particolare si vede che, non essendo le celle in edit, nel caso del secondo componente, viene ritornato il componente JScrollPane. Va bene cosi

Prova2: si clicca su una cella JTable, si scrive qualcosa (per entrare in edit) e si preme TAB
In console si vede il passaggio nel metodo getComponentAfter ; in particolare si vede che, avendo il focus la JTable, viene ritornato il componente JTable. Va bene cosi

Prova3: si clicca su una cella JTable, si scrive qualcosa (per entrare in edit) e si preme ShiftTAB
Non succede niente almeno a livello di focustraversalpolicy
Se si preme ancora ShiftTab
In console si vede il passaggio nel metodo getComponentBefore ; in particolare si vede che viene ritornato il componente JTextField usato per l'edit della cella!!!!

Codice sorgente - presumibilmente Java

  1. import java.awt.BorderLayout;
  2. import java.awt.Component;
  3. import java.awt.Container;
  4. import java.awt.FocusTraversalPolicy;
  5. import java.awt.KeyboardFocusManager;
  6. import java.awt.event.ActionEvent;
  7.  
  8.  
  9. import javax.swing.AbstractAction;
  10. import javax.swing.ActionMap;
  11. import javax.swing.DefaultCellEditor;
  12. import javax.swing.JFrame;
  13. import javax.swing.JPanel;
  14. import javax.swing.JRootPane;
  15. import javax.swing.JScrollPane;
  16. import javax.swing.JTable;
  17. import javax.swing.JTextField;
  18. import javax.swing.SwingUtilities;
  19.  
  20. public class Prova2
  21. {
  22.     public static final Double VideoDefaultFontIncrementWidth = 0.92;
  23.     public static final Double VideoDefaultFontIncrementHeight = 1.5;
  24.    
  25.     public static void main(String[] args)
  26.     {
  27.         SwingUtilities.invokeLater(new Runnable()
  28.         {
  29.             @Override
  30.             public void run()
  31.             {
  32.                 new Prova2();
  33.             }
  34.         });
  35.     }
  36.  
  37.  
  38.     public Prova2()
  39.     {
  40.         JFrame frame = new JFrame("Prova");
  41.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  42.         //
  43.         Object[] columnHeaders = {"Codice", "Nome", "Prezzo", "Data", "Noedit"};
  44.         Object rows[][] = {
  45.             { "A", "About", 44.36, null, "aa" },
  46.             { "B", "Boy", 44.84, null, "aa" },
  47.             { "C", "Cat", 463.63, null, "aa" },
  48.             { "D", "Day", 27.14, null, "aa" },
  49.             { "E", "Eat", 44.57, null, "aa" },
  50.             { "F", "Fail", 23.15, null, "aa" },
  51.             { "G", "Good", 4.40, null, "aa" },
  52.             { "H", "Hot", 24.96, null, "aa" },
  53.             { "I", "Ivey", 5.45, null, "aa" },
  54.             { "J", "Jack", 49.54, null, "aa" },
  55.             { "K", "Kids", 280.00, null, "aa" },
  56.             { "2A", "About", 44.36, null, "aa" },
  57.             { "2B", "Boy", 44.84, null, "aa" },
  58.             { "2C", "Cat", 463.63, null, "aa" },
  59.             { "2D", "Day", 27.14, null, "aa"},
  60.             { "2E", "Eat", 44.57, null, "aa" },
  61.             { "2F", "Fail", 23.15, null, "aa" },
  62.             { "2G", "Good", 4.40, null, "aa" },
  63.             { "2H", "Hot", 24.96, null, "aa" },
  64.             { "2I", "Ivey", 5.45, null, "aa" },
  65.             { "2J", "Jack", 49.54, null, "aa" },
  66.             { "2K", "Kids", 280.00, null, "aa" } };
  67.         //
  68.         // text 1
  69.         JTextField Text1 = new JTextField("");
  70.         Text1.setName("Text1");
  71.         frame.add(Text1, BorderLayout.NORTH);
  72.         //
  73.         // JTable soluzione 2
  74.         JTable myTable = new JTable(rows, columnHeaders);
  75.         myTable.setName("Table");
  76.         myTable.setFillsViewportHeight(true);
  77.         myTable.putClientProperty("autoStartsEdit", true);
  78.         myTable.putClientProperty("terminateEditOnFocusLost", true);
  79.         ////myTable.setAutoCreateColumnsFromModel(false);
  80.         ////myTable.getSelectionModel().addListSelectionListener(new myListSelectionHandler());
  81.         ////myTable.addFocusListener(new myTableFocusListener());
  82.             // disabilita CtrlTab e CtrlShiftTab come uscita di campo jTable
  83.             // che tornano ad essere sentiti come traversal focus del tabbedpane per tab successivo e precedente
  84.         ////myTable.setFocusTraversalKeysEnabled(false);
  85.             // disabilita Tab e ShiftTab come spostamento tra celle
  86.             // che tornano ad essere sentiti come traversal focus del tabbedpane per campo successivo e precedente
  87.         ActionMap myTableActionMap = myTable.getActionMap();
  88.         myTableActionMap.put("selectPreviousColumnCell", new myPreviousFocusHandler());
  89.         myTableActionMap.put("selectNextColumnCell", new myNextFocusHandler());
  90.         for (int i = 0; i < myTable.getColumnCount()-1; i++)
  91.         {
  92.             JTextField myTextField = new JTextField();
  93.             myTable.getColumn(columnHeaders[i]).setCellEditor(new DefaultCellEditor(myTextField));
  94.         }
  95.         JScrollPane pane = new JScrollPane(myTable);
  96.         frame.add(pane, BorderLayout.CENTER);        
  97.         //
  98.         // text2
  99.         JTextField Text2 = new JTextField("");
  100.         Text2.setName("Text1");
  101.         frame.add(Text2, BorderLayout.SOUTH);
  102.         //
  103.         // frame
  104.         frame.setFocusTraversalPolicy(new MyFocusTraversalPolicy());
  105.         frame.setSize(800, 400);
  106.         frame.setVisible(true);
  107.     }
  108.    
  109.     public static class MyFocusTraversalPolicy extends FocusTraversalPolicy
  110.     {
  111.         @Override
  112.         public Component getComponentAfter(Container arg0, Component arg1)
  113.         {
  114.             System.out.println("getComponentAfter: "+arg1.toString());
  115.             JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
  116.             JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
  117.             if (arg1 instanceof JPanel == true)
  118.             {
  119.                 return getFirstComponent(arg0);
  120.             }
  121.             int myNewPosition = 0;
  122.             myNewPosition = myComponentPosition(myPanel, arg1);
  123.             myNewPosition = myComponentNext(myPanel, myNewPosition, 1);
  124.             if (myNewPosition > -1)
  125.             {
  126.                 return myComponent(myPanel, myNewPosition);
  127.             }
  128.             else
  129.             {
  130.                 return getFirstComponent(arg0);
  131.             }
  132.         }
  133.         @Override
  134.         public Component getComponentBefore(Container arg0, Component arg1)
  135.         {
  136.             System.out.println("getComponentBefore: "+arg1.toString());
  137.             JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
  138.             JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
  139.             if (arg1 instanceof JPanel == true)
  140.             {
  141.                 return getFirstComponent(arg0);
  142.             }
  143.             int myNewPosition = 0;
  144.             myNewPosition = myComponentPosition(myPanel, arg1);
  145.             myNewPosition = myComponentNext(myPanel, myNewPosition, -1);
  146.             if (myNewPosition > -1)
  147.             {
  148.                 return myComponent(myPanel, myNewPosition);
  149.             }
  150.             else
  151.             {
  152.                 return getLastComponent(arg0);
  153.             }
  154.         }
  155.         @Override
  156.         public Component getDefaultComponent(Container arg0)
  157.         {
  158.             System.out.println("getDefaultComponent: ");
  159.             JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
  160.             JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
  161.             return myPanel.getComponent(0);
  162.         }
  163.         @Override
  164.         public Component getFirstComponent(Container arg0)
  165.         {
  166.             System.out.println("getFirstComponent: ");
  167.             JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
  168.             JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
  169.             return myPanel.getComponent(0);
  170.         }
  171.         @Override
  172.         public Component getLastComponent(Container arg0)
  173.         {
  174.             System.out.println("getLastComponent: ");
  175.             JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
  176.             JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
  177.             return myPanel.getComponent(myPanel.getComponentCount()-1);
  178.         }
  179.         // ritorna la posizione del componente dato
  180.         private int myComponentPosition(Container parm_Container, Component parm_Component)
  181.         {
  182.             for (int i = 0; i < parm_Container.getComponentCount(); i++)
  183.             {
  184.                 if (parm_Container.getComponent(i) == parm_Component)
  185.                 {
  186.                     return i;
  187.                 }
  188.             }
  189.             return -1;
  190.         }
  191.         // ritorna la posizione del componente successivo o precedente rispetto al dato
  192.         private int myComponentNext(Container parm_Container, int parm_Position, int parm_Increment)
  193.         {
  194.             for (int i = parm_Position + parm_Increment; i > -1 && i < parm_Container.getComponentCount(); i = i + parm_Increment)
  195.             {
  196.                 if (parm_Container.getComponent(i).isEnabled() && parm_Container.getComponent(i).isFocusable())
  197.                 {
  198.                     return i;
  199.                 }
  200.             }
  201.             return -1;
  202.         }
  203.  
  204.  
  205.         // ritorna il componente alla posizione
  206.         private Component myComponent(Container parm_Container, int parm_Position)
  207.         {
  208.             return parm_Container.getComponent(parm_Position);
  209.         }
  210.     }
  211.    
  212.    
  213.     public class myPreviousFocusHandler extends AbstractAction
  214.     {
  215.         private static final long serialVersionUID = 1L;
  216.  
  217.  
  218.         @Override
  219.         public void actionPerformed(ActionEvent arg0)
  220.         {
  221.             KeyboardFocusManager myManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
  222.             myManager.focusPreviousComponent();
  223.         }
  224.     }
  225.  
  226.  
  227.     public class myNextFocusHandler extends AbstractAction
  228.     {
  229.         private static final long serialVersionUID = 1L;
  230.  
  231.  
  232.         @Override
  233.         public void actionPerformed(ActionEvent arg0)
  234.         {
  235.             KeyboardFocusManager myManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
  236.             myManager.focusNextComponent();
  237.         }
  238.  
  239.  
  240.     }
  241.    
  242. }




PM Quote