Oppure

Loading
16/03/20 15:36
PaoloDaPrato
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

ActionMap myTableActionMap = myTable.getActionMap();
myTableActionMap.put("selectPreviousColumnCell", new myPreviousFocusHandler());
myTableActionMap.put("selectNextColumnCell", new myNextFocusHandler());
public class myPreviousFocusHandler extends AbstractAction
{
public void actionPerformed(ActionEvent evt)
{
KeyboardFocusManager myManager = KeyboardFocusManager.getCurrentKeyboardFocusManage r();
myManager.focusPreviousComponent();
}
}
public class myNextFocusHandler extends AbstractAction
{
public void actionPerformed(ActionEvent evt)
{
KeyboardFocusManager myManager = KeyboardFocusManager.getCurrentKeyboardFocusManage r();
myManager.focusNextComponent();
}
}


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 16/03/20 15:38
aaa
24/03/20 7:11
PaoloDaPrato
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!!!!

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.FocusTraversalPolicy;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;


import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.DefaultCellEditor;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class Prova2
{
    public static final Double VideoDefaultFontIncrementWidth = 0.92;
    public static final Double VideoDefaultFontIncrementHeight = 1.5;
    
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                new Prova2();
            }
        });
    }


    public Prova2()
    {
        JFrame frame = new JFrame("Prova");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //
        Object[] columnHeaders = {"Codice", "Nome", "Prezzo", "Data", "Noedit"};
        Object rows[][] = { 
            { "A", "About", 44.36, null, "aa" }, 
            { "B", "Boy", 44.84, null, "aa" }, 
            { "C", "Cat", 463.63, null, "aa" }, 
            { "D", "Day", 27.14, null, "aa" }, 
            { "E", "Eat", 44.57, null, "aa" }, 
            { "F", "Fail", 23.15, null, "aa" }, 
            { "G", "Good", 4.40, null, "aa" }, 
            { "H", "Hot", 24.96, null, "aa" }, 
            { "I", "Ivey", 5.45, null, "aa" }, 
            { "J", "Jack", 49.54, null, "aa" }, 
            { "K", "Kids", 280.00, null, "aa" }, 
            { "2A", "About", 44.36, null, "aa" }, 
            { "2B", "Boy", 44.84, null, "aa" }, 
            { "2C", "Cat", 463.63, null, "aa" }, 
            { "2D", "Day", 27.14, null, "aa"}, 
            { "2E", "Eat", 44.57, null, "aa" }, 
            { "2F", "Fail", 23.15, null, "aa" }, 
            { "2G", "Good", 4.40, null, "aa" }, 
            { "2H", "Hot", 24.96, null, "aa" }, 
            { "2I", "Ivey", 5.45, null, "aa" }, 
            { "2J", "Jack", 49.54, null, "aa" }, 
            { "2K", "Kids", 280.00, null, "aa" } };
        //
        // text 1
        JTextField Text1 = new JTextField("");
        Text1.setName("Text1");
        frame.add(Text1, BorderLayout.NORTH);
        //
        // JTable soluzione 2
        JTable myTable = new JTable(rows, columnHeaders);
        myTable.setName("Table");
        myTable.setFillsViewportHeight(true);
        myTable.putClientProperty("autoStartsEdit", true);
        myTable.putClientProperty("terminateEditOnFocusLost", true);
        ////myTable.setAutoCreateColumnsFromModel(false);
        ////myTable.getSelectionModel().addListSelectionListener(new myListSelectionHandler());
        ////myTable.addFocusListener(new myTableFocusListener());
            // disabilita CtrlTab e CtrlShiftTab come uscita di campo jTable
            // che tornano ad essere sentiti come traversal focus del tabbedpane per tab successivo e precedente
        ////myTable.setFocusTraversalKeysEnabled(false);
            // disabilita Tab e ShiftTab come spostamento tra celle
            // che tornano ad essere sentiti come traversal focus del tabbedpane per campo successivo e precedente
        ActionMap myTableActionMap = myTable.getActionMap();
        myTableActionMap.put("selectPreviousColumnCell", new myPreviousFocusHandler());
        myTableActionMap.put("selectNextColumnCell", new myNextFocusHandler());
        for (int i = 0; i < myTable.getColumnCount()-1; i++)
        {
            JTextField myTextField = new JTextField();
            myTable.getColumn(columnHeaders[i]).setCellEditor(new DefaultCellEditor(myTextField));
        }
        JScrollPane pane = new JScrollPane(myTable);
        frame.add(pane, BorderLayout.CENTER);        
        //
        // text2
        JTextField Text2 = new JTextField("");
        Text2.setName("Text1");
        frame.add(Text2, BorderLayout.SOUTH);
        //
        // frame
        frame.setFocusTraversalPolicy(new MyFocusTraversalPolicy());
        frame.setSize(800, 400);
        frame.setVisible(true);
    }
    
    public static class MyFocusTraversalPolicy extends FocusTraversalPolicy
    {
        @Override
        public Component getComponentAfter(Container arg0, Component arg1)
        {
            System.out.println("getComponentAfter: "+arg1.toString());
            JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
            JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
            if (arg1 instanceof JPanel == true)
            {
                return getFirstComponent(arg0);
            }
            int myNewPosition = 0;
            myNewPosition = myComponentPosition(myPanel, arg1);
            myNewPosition = myComponentNext(myPanel, myNewPosition, 1);
            if (myNewPosition > -1)
            {
                return myComponent(myPanel, myNewPosition);
            }
            else
            {
                return getFirstComponent(arg0);
            }
        }
        @Override
        public Component getComponentBefore(Container arg0, Component arg1)
        {
            System.out.println("getComponentBefore: "+arg1.toString());
            JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
            JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
            if (arg1 instanceof JPanel == true)
            {
                return getFirstComponent(arg0);
            }
            int myNewPosition = 0;
            myNewPosition = myComponentPosition(myPanel, arg1);
            myNewPosition = myComponentNext(myPanel, myNewPosition, -1);
            if (myNewPosition > -1)
            {
                return myComponent(myPanel, myNewPosition);
            }
            else
            {
                return getLastComponent(arg0);
            }
        }
        @Override
        public Component getDefaultComponent(Container arg0)
        {
            System.out.println("getDefaultComponent: ");
            JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
            JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
            return myPanel.getComponent(0);
        }
        @Override
        public Component getFirstComponent(Container arg0)
        {
            System.out.println("getFirstComponent: ");
            JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
            JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
            return myPanel.getComponent(0);
        }
        @Override
        public Component getLastComponent(Container arg0)
        {
            System.out.println("getLastComponent: ");
            JRootPane myRootPane=(JRootPane)arg0.getComponent(0);
            JPanel myPanel = (JPanel) myRootPane.getLayeredPane().getComponent(0);
            return myPanel.getComponent(myPanel.getComponentCount()-1);
        }
        // ritorna la posizione del componente dato
        private int myComponentPosition(Container parm_Container, Component parm_Component)
        {
            for (int i = 0; i < parm_Container.getComponentCount(); i++)
            {
                if (parm_Container.getComponent(i) == parm_Component)
                {
                    return i;
                }
            }
            return -1;
        }
        // ritorna la posizione del componente successivo o precedente rispetto al dato
        private int myComponentNext(Container parm_Container, int parm_Position, int parm_Increment)
        {
            for (int i = parm_Position + parm_Increment; i > -1 && i < parm_Container.getComponentCount(); i = i + parm_Increment)
            {
                if (parm_Container.getComponent(i).isEnabled() && parm_Container.getComponent(i).isFocusable())
                {
                    return i;
                }
            }
            return -1;
        }


        // ritorna il componente alla posizione
        private Component myComponent(Container parm_Container, int parm_Position)
        {
            return parm_Container.getComponent(parm_Position);
        }
    }
    
    
    public class myPreviousFocusHandler extends AbstractAction
    {
        private static final long serialVersionUID = 1L;


        @Override
        public void actionPerformed(ActionEvent arg0)
        {
            KeyboardFocusManager myManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
            myManager.focusPreviousComponent();
        }
    }


    public class myNextFocusHandler extends AbstractAction
    {
        private static final long serialVersionUID = 1L;


        @Override
        public void actionPerformed(ActionEvent arg0)
        {
            KeyboardFocusManager myManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
            myManager.focusNextComponent();
        }


    }
    
}



aaa