[Risolto] Intercettare la combinazione di tasti <Ctrl><Tab>

di il
12 risposte

[Risolto] Intercettare la combinazione di tasti <Ctrl><Tab>

Carissimi amici,
sto tribolando una cifra per gestire lo spostamento da una form ad un'altra con la combinazione di tasti <Ctrl><Tab>,
cosa che con Visual Basic era semplicissima, poiché gli eventi associati alla Form venivano intercettati prima di quelli associati agli altri oggetti, per cui era semplice intercettare la sequenza:
If (KeyCode = vbKeyTab) And (Shift And vbCtrlMask) Then
a livello di Form.

In Java purtroppo non mi risulta così semplice, perché dalle mie prove mi sembra di capire che gli eventi vengono intercettati dando la precedenza all'oggetto che ha il focus nel momento della pressione dei tasti.

In rete ho trovato tanta roba, compresi esempi, che ho utilizzato per le prove, ma ancora non ho capito un ... piffero.
Per esempio qui: https://forum.html.it/forum/showthread/t-999208.htm
viene suggerita una soluzione tramite KeyStroke
che però non riesco ad applicare perché getInputMap non é applicabile alla JFrame (this).

Fin'ora per gestire l'intercettazione di tasti particolari ho utilizzato gli eventi associati ai vari oggetti, menù etc. come i KeyReleased.
Per intercettare invece i tasti prima che vengano gestiti dagli eventi degli oggetti, mi sembra di aver capito che l'unica soluzione sia aggiungere un listener alla finestra o alla tastiera.

Ho trovato un esempio che con KeyEventDispatcher intercetta i tasti prima di ogni altro oggetto ma non più tasti contemporaneamente, come la combinazione <Ctrl><Tab>, infatti al momento intercetto i tasti VK_PAGE_DOWN e VK_PAGE_UP.

Inoltre nel fare le prove ho scoperto che:
1) Ad ogni pressione di un tasto il KeyEventDispatcher viene attivato due volte.
2) Le form che chiudo con la dispose() in realtà non vengono distrutte ma diventano semplicemente invisibili.

Faccio queste precisazioni perché di seguito riporto un progettino che ho realizzato apposta per le prove, riportando l'essenziale, e chi volesse darmi una mano lo può provare, ma vedrà dei metodi per evitare la moltiplicazione delle form e la ripetizione dell'attivazione del KeyEventDispatcher.

Se qualche buona anima riesce a darmi la giusta dritta per risolvere il mio problema gli sarò eternamente grato.

Ah, come ambiente di sviluppo uso NetBeans 7.3.1 quindi le form riportano le itruzioni di NetBeas.

Form principale

package provagui;

import java.awt.Frame;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;

//================================================================================
public class Principale extends javax.swing.JFrame {
  boolean secondTime = false;
  String curForm;
  KeyEventDispatcher MioControlloTasti;
//================================================================================
  public Principale() {
    initComponents();
    this.MioControlloTasti = new KeyEventDispatcher() {
    @Override
    public boolean dispatchKeyEvent(KeyEvent e) {
      System.out.println("<dispatchKeyEvent> " + e.getKeyCode() + " secondTime = " + secondTime);
      if (secondTime) {
        System.out.println("<dispatchKeyEvent> uscita falsa");
        secondTime = false;
        return false;
      } 
      switch (e.getKeyCode()) {
        case KeyEvent.VK_PAGE_DOWN: {
          System.out.println("<VK_PAGE_DOWN>");
          curForm = SwitchForm(curForm, false);
          secondTime = true;
          return true;
        }
        case KeyEvent.VK_PAGE_UP: {
          System.out.println("<VK_PAGE_UP>");
          curForm = SwitchForm(curForm, true);
          secondTime = true;
          return true;
        }
      }
      System.out.println("<dispatchKeyEvent> uscita vera");
      secondTime = true;
      return false;
    } 
  }; 
  KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this.MioControlloTasti);
}
//================================================================================
  @SuppressWarnings("unchecked")
  // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
  private void initComponents() {

    jMenuBar1 = new javax.swing.JMenuBar();
    MnuFile = new javax.swing.JMenu();
    ItemShowWin = new javax.swing.JMenuItem();
    ItemExit = new javax.swing.JMenuItem();
    MnuWin = new javax.swing.JMenu();
    ItemWinA = new javax.swing.JMenuItem();
    ItamWinB = new javax.swing.JMenuItem();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    MnuFile.setMnemonic('f');
    MnuFile.setText("File");

    ItemShowWin.setMnemonic('m');
    ItemShowWin.setText("Mostra finestre");
    ItemShowWin.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        ItemShowWinActionPerformed(evt);
      }
    });
    MnuFile.add(ItemShowWin);

    ItemExit.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_ESCAPE, 0));
    ItemExit.setMnemonic('u');
    ItemExit.setText("Uscita");
    MnuFile.add(ItemExit);

    jMenuBar1.add(MnuFile);

    MnuWin.setMnemonic('n');
    MnuWin.setText("Finestre");

    ItemWinA.setMnemonic('a');
    ItemWinA.setText("Finestra A");
    ItemWinA.setToolTipText("");
    ItemWinA.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        ItemWinAActionPerformed(evt);
      }
    });
    MnuWin.add(ItemWinA);

    ItamWinB.setMnemonic('b');
    ItamWinB.setText("Finestra B");
    ItamWinB.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        ItamWinBActionPerformed(evt);
      }
    });
    MnuWin.add(ItamWinB);

    jMenuBar1.add(MnuWin);

    setJMenuBar(jMenuBar1);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGap(0, 178, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGap(0, 63, Short.MAX_VALUE)
    );

    pack();
  }// </editor-fold>                        
  private void ItemWinAActionPerformed(java.awt.event.ActionEvent evt) {                                         
    if (!EsisteFinestra("A")) {
      new A().setVisible(true);
    }
  }                                        
  private void ItamWinBActionPerformed(java.awt.event.ActionEvent evt) {                                         
    if (!EsisteFinestra("B")) {
      new B().setVisible(true);
    }
  }                                        
  private void ItemShowWinActionPerformed(java.awt.event.ActionEvent evt) {                                            
    MostraFinestra();
  }                                           
//================================================================================
  public boolean EsisteFinestra(String curForm) {
    boolean esiste = false;
    Frame[] frames = Frame.getFrames();
    for (final Frame frame : frames) {
      System.out.println("CercaFinestra: " + frame.getName() 
                                            + " Visibile = " + frame.isVisible());
      if (frame.getName().equals(curForm)) {
        esiste = true;
        if (!frame.isVisible()) frame.setVisible(esiste);
        frame.requestFocus();
      }
    }
    return esiste;
  }
//================================================================================
  public void MostraFinestra() {
    Frame[] frames = Frame.getFrames();
    for (final Frame frame : frames) {
      System.out.println("CercaFinestra: " + frame.getName() 
                                            + " Visibile = " + frame.isVisible());
    }
  }
//================================================================================
  public String SwitchForm(String curForm, boolean GoBack) {
    int ii = 0;
    Frame[] frames = Frame.getFrames();
    System.out.println("SwitchForm: Frames = " + frames.length + " curForm = " + curForm);
    do {
      System.out.println("SwitchForm: (" + ii + ") " + frames[ii].getName());
      if (frames[ii].getName().equals(curForm)) break;
      ii++;
    } while (ii < frames.length);
    do {
      if (GoBack) {
        if (ii == 0) ii = frames.length;
        ii--;
      } else {
        if (ii >= frames.length-1) ii = -1;
        ii++;
      }
    } while (!frames[ii].isVisible());
    System.out.println("SwitchForm: transferFocus -> (" + ii + ") " + frames[ii].getName());
    frames[ii].requestFocus();
    return frames[ii].getName();
  }
//================================================================================
  public static void main(String args[]) {
    try {
      for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
        if ("Nimbus".equals(info.getName())) {
          javax.swing.UIManager.setLookAndFeel(info.getClassName());
          break;
        }
      }
    } catch (ClassNotFoundException ex) {
      java.util.logging.Logger.getLogger(Principale.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
      java.util.logging.Logger.getLogger(Principale.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
      java.util.logging.Logger.getLogger(Principale.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
      java.util.logging.Logger.getLogger(Principale.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    java.awt.EventQueue.invokeLater(new Runnable() {
      public void run() {
        new Principale().setVisible(true);
      }
    });
  }
  // Variables declaration - do not modify                     
  private javax.swing.JMenuItem ItamWinB;
  private javax.swing.JMenuItem ItemExit;
  private javax.swing.JMenuItem ItemShowWin;
  private javax.swing.JMenuItem ItemWinA;
  private javax.swing.JMenu MnuFile;
  private javax.swing.JMenu MnuWin;
  private javax.swing.JMenuBar jMenuBar1;
  // End of variables declaration                   
}
Form A
package provagui;
public class A extends javax.swing.JFrame {
  public A() {
    initComponents();
    this.setTitle("Finestra A");
  }
  @SuppressWarnings("unchecked")
  // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
  private void initComponents() {

    setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
    setName("A"); // NOI18N

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGap(0, 224, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGap(0, 131, Short.MAX_VALUE)
    );

    pack();
  }// </editor-fold>                        
  public static void main(String args[]) {
    /* Set the Nimbus look and feel */
    //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
     * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
     */
    try {
      for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
        if ("Nimbus".equals(info.getName())) {
          javax.swing.UIManager.setLookAndFeel(info.getClassName());
          break;
        }
      }
    } catch (ClassNotFoundException ex) {
      java.util.logging.Logger.getLogger(A.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
      java.util.logging.Logger.getLogger(A.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
      java.util.logging.Logger.getLogger(A.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
      java.util.logging.Logger.getLogger(A.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    //</editor-fold>
    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
      public void run() {
        new A().setVisible(true);
      }
    });
  }
  // Variables declaration - do not modify                     
  // End of variables declaration                   
}
Form B
package provagui;
public class B extends javax.swing.JFrame {
  public B() {
    initComponents();
    this.setTitle("Finestra B");
  }
  @SuppressWarnings("unchecked")
  // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
  private void initComponents() {

    setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
    setName("B"); // NOI18N

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGap(0, 270, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGap(0, 161, Short.MAX_VALUE)
    );

    pack();
  }// </editor-fold>                        
  public static void main(String args[]) {
    /* Set the Nimbus look and feel */
    //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
     * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
     */
    try {
      for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
        if ("Nimbus".equals(info.getName())) {
          javax.swing.UIManager.setLookAndFeel(info.getClassName());
          break;
        }
      }
    } catch (ClassNotFoundException ex) {
      java.util.logging.Logger.getLogger(B.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
      java.util.logging.Logger.getLogger(B.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
      java.util.logging.Logger.getLogger(B.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
      java.util.logging.Logger.getLogger(B.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    //</editor-fold>
    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
      public void run() {
        new B().setVisible(true);
      }
    });
  }
  // Variables declaration - do not modify                     
  // End of variables declaration                   
}

12 Risposte

  • Re: [Risolto] Intercettare la combinazione di tasti <Ctrl><Tab>

    ZioCrick ha scritto:


    sto tribolando una cifra per gestire lo spostamento da una form ad un'altra con la combinazione di tasti <Ctrl><Tab>
    Quindi, per riassumere, hai N finestre (frame ma precisamente JFrame) e vuoi usare "globalmente" nella tua applicazione Ctrl+Tab per switchare da un frame all'altro?

    ZioCrick ha scritto:


    1) Ad ogni pressione di un tasto il KeyEventDispatcher viene attivato due volte.
    Scusa ma banalmente hai "stampato" l'oggetto KeyEvent che così vedi subito perché hai più eventi?? Il motivo c'è ...
  • Re: [Risolto] Intercettare la combinazione di tasti <Ctrl><Tab>

    andbin ha scritto:


    Quindi, per riassumere, hai N finestre (frame ma precisamente JFrame) e vuoi usare "globalmente" nella tua applicazione Ctrl+Tab per switchare da un frame all'altro?
    Esattamente esatto.
    E ovviamente anche il Ctrl+Shift+Tab per andare al contrario (Così come succede in quasi tutte le applicazioni MDI).

    ZioCrick ha scritto:


    Scusa ma banalmente hai "stampato" l'oggetto KeyEvent che così vedi subito perché hai più eventi?? Il motivo c'è ...
    Non capisco, vuoi dire che la stampa del e.getKeyCode() mi genera il secondo evento?
    Ho appena provato a togliere la riga della stampa, ma mi genera comunque due eventi, e ovviamente mi salta una finestra, ovvero invece di passare dalla "Principale" alla "A", mi passa alla "B".

    E comunque, come faccio ad intercettare le combinazioni Ctrl+Tab e Ctrl+Shift+Tab ?
  • Re: [Risolto] Intercettare la combinazione di tasti <Ctrl><Tab>

    ZioCrick ha scritto:


    Esattamente esatto.
    E ovviamente anche il Ctrl+Shift+Tab per andare al contrario
    Chiaro.

    ZioCrick ha scritto:


    (Così come succede in quasi tutte le applicazioni MDI).
    In Java è anche possibile fare applicazioni nel senso MDI, cioè una finestra principale che contiene N finestre.

    ZioCrick ha scritto:


    Non capisco, vuoi dire che la stampa del e.getKeyCode() mi genera il secondo evento?
    Se facessi:

    System.out.println(e);

    (e è il KeyEvent) scopriresti che ......


    EDIT: e giusto per chiarire:

    ZioCrick ha scritto:


    2) Le form che chiudo con la dispose() in realtà non vengono distrutte ma diventano semplicemente invisibili.
    Il dispose() nasconde la finestra E rilascia tutte le risorse "native" usate dalla finestra. Ma l'oggetto JFrame resta finché è "raggiungibile". Se nel tuo codice (o altro codice) non hai più alcun riferimento a quella finestra di cui è stato fatto dispose, allora il JFrame è tecnicamente "eleggibile" per il g.c. (come per qualunque altro oggetto non più raggiungibile). Solo che magari il g.c. non lo traccia subito. Appena lo fa, il JFrame sparisce dall'array ottenuto dal Frame.getFrames()
  • Re: [Risolto] Intercettare la combinazione di tasti <Ctrl><Tab>

    In Java è anche possibile fare applicazioni nel senso MDI, cioè una finestra principale che contiene N finestre.
    Scusa, mi sono sbagliato. Intendevo le applicazioni SDI.
    Le MDI non mi piacciono. Preferisco finestre indipendenti per ogni funzione dell'applicativo, anche perché così posso confrontare il contenuto di più finestre contemporaneamente, che in certi casi è molto utile.
    Se facessi:

    System.out.println(e);

    (e è il KeyEvent) scopriresti che ......
    Eh ... ho scoperto che ci sono anche il getModifiers e il getExtendedKeyCode ... ma non ho capito come sfruttarli ... perché ...
    ho scoperto anche (togliendo tutto tranne la stampa) che ci sono tasti che generano 2 eventi, come i tasti funzione, le freccette, i page down e up, e invece i tasti alfanumerici generano addirittura 3 eventi, per esempio:
    La barra spaziatrice genera la sequenza: 32, 0, 32.
    Ovvero il primo getKeyCode mi da il codice ASCII del carattere, il secondo mi da 0 e il terzo è uguale al primo.
    Se pigio la combinazione Ctrl+Tab ottengo la sequenza 17, 9, 9, 17.
    Alla fine, verificando il valore di due eventi consecutivi riesco ad intercettare la sequenza Ctrl+Tab, ma non funziona sempre ...
    Capisco che mi vuoi spingere a trovare da solo la soluzione, ma almeno sono sulla buona strada, o c'è qualche altro sistema, magari più semplice o più affidabile?

    EDIT: e giusto per chiarire:
    Il dispose() nasconde la finestra E rilascia tutte le risorse "native" usate dalla finestra. Ma l'oggetto JFrame resta finché è "raggiungibile". Se nel tuo codice (o altro codice) non hai più alcun riferimento a quella finestra di cui è stato fatto dispose, allora il JFrame è tecnicamente "eleggibile" per il g.c. (come per qualunque altro oggetto non più raggiungibile). Solo che magari il g.c. non lo traccia subito. Appena lo fa, il JFrame sparisce dall'array ottenuto dal Frame.getFrames()
    Beh, questa almeno conferma le mie prove e allora ho fatto bene ad aggiungere la EsisteFinestra così evito di creare troppe istanze degli stessi JFrame, ma riutilizzo le precedenti.
  • Re: [Risolto] Intercettare la combinazione di tasti <Ctrl><Tab>

    Aggiornamento:
    di fatto è un casino ...
    nel senso che, mi sembra di capire che il <Ctrl> lo devo intercettare in modo a se stante, come primo tasto della sequenza.
    Poi devo verificare il successivo getKeyCode se è il <Tab> e a questo punto posso verificare il getModifiers per capire se fa parte della sequenza oppure è stato premuto da solo.
    Inoltre dal getModifiers posso capire se è stato premuto lo <Shift> per andare in senso inverso nello spostamento tra le finestre.
    Così facendo riesco ad intercettare le due sequenze, ma non ho ancora trovato la soluzione ottimale, perché se dopo il <Ctrl><Tab> premo un singolo <Tab. o un <Ctrl> mi produce ancora il cambiamento di finestra.
  • Re: [Risolto] Intercettare la combinazione di tasti <Ctrl><Tab>

    ZioCrick ha scritto:


    nel senso che, mi sembra di capire che il <Ctrl> lo devo intercettare in modo a se stante, come primo tasto della sequenza.
    No.
    Ti mostro appena riesco un esempio.
  • Re: [Risolto] Intercettare la combinazione di tasti <Ctrl><Tab>

    Prova questo:
    import java.awt.Frame;
    import java.awt.KeyEventDispatcher;
    import java.awt.KeyboardFocusManager;
    import java.awt.Window;
    import java.awt.event.KeyEvent;
    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;
    
    public class FrameSwitcher implements KeyEventDispatcher {
        @Override
        public boolean dispatchKeyEvent(KeyEvent e) {
            if (e.getID() == KeyEvent.KEY_RELEASED && e.getKeyCode() == KeyEvent.VK_TAB && e.isControlDown()) {
                switchToNextFrame();
                return true;
            }
    
            return false;
        }
    
    
        private void switchToNextFrame() {
            Frame[] frames = Frame.getFrames();
            Window activeWindow = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
    
            int i;
            for (i = 0; i < frames.length; i++) {
                if (frames[i] == activeWindow) {
                    break;
                }
            }
    
            for (int n = 1; n <= frames.length; n++) {
                int nextIdx = (i+n) % frames.length;
                Frame nextFrame = frames[nextIdx];
                if (nextFrame.isDisplayable()) {            // <------ Da correggere, vedi EDIT in fondo
                    nextFrame.setState(Frame.NORMAL);
                    nextFrame.toFront();
                    break;
                }
            }
        }
    
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    FrameSwitcher switcher = new FrameSwitcher();
                    KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(switcher);
    
                    // alcuni frame giusto per prova
                    new TestFrame("Frame 1", 100, 100);
                    new TestFrame("Frame 2", 200, 200);
                    new TestFrame("Frame 3", 300, 300);
                    new TestFrame("Frame 4", 400, 400);
                }
            });
        }
    }
    
    
    class TestFrame extends JFrame {
        private static final long serialVersionUID = 1L;
    
        public TestFrame(String title, int x, int y) {
            super(title);
            setSize(300, 200);
            setLocation(x, y);
            setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            setVisible(true);
        }
    }
    Nota diverse cose, innanzitutto il test nel dispatchKeyEvent. Il test è molto semplice, dice semplicemente: "se è stato rilasciato il Tab E c'è il Control (Ctrl) premuto". E' tutto lì! Non c'è da fare cose "strane" ...

    Poi cerca di capire perché ho fatto quella logica nel switchToNextFrame. C'è un motivo preciso, non ho tempo di spiegarlo bene ora.

    Chiaramente è solo un ESEMPIO (da cui puoi partire). Non sono sicuro che sia in grado di gestire tutti gli scenari possibili. Ma è perlomeno in grado di "saltare" i frame disposed (e non ancora garbage collected) e anche di riportare in stato normale i frame "minimizzati".
    E se vuoi fare lo switch all'indietro ... è da fare in più, naturalmente (ma è una logica molto simile).


    EDIT: piccola correzione. Invece di
    if (nextFrame.isDisplayable())

    è meglio fare:
    if (nextFrame.isVisible())

    perché così anche le finestre hidden (ma non disposed) vengono correttamente saltate. Per le finestre minimizzate, continua ad andar bene: una finestra minimizzata è comunque "visible".
  • Re: [Risolto] Intercettare la combinazione di tasti <Ctrl><Tab>

    andbin ha scritto:


    Nota diverse cose, innanzitutto il test nel dispatchKeyEvent. Il test è molto semplice, dice semplicemente: "se è stato rilasciato il Tab E c'è il Control (Ctrl) premuto". E' tutto lì! Non c'è da fare cose "strane" ...
    Caro andbin ... sei un mito!
    Di fatto non avevo ancora scoperto l'uso dei KeyEvent.KEY_RELEASED e e.isControlDown() per riconoscere la sequenza Ctrl+Tab.

    andbin ha scritto:


    Poi cerca di capire perché ho fatto quella logica nel switchToNextFrame. C'è un motivo preciso, non ho tempo di spiegarlo bene ora.
    Mi sembra di capire che serva a partire dalla form attiva, cosa che io ho risolto con l'argomento curForm della mia SwitchForm.
    Sicuramente la tua soluzione è più elegante.

    andbin ha scritto:


    E se vuoi fare lo switch all'indietro ... è da fare in più, naturalmente (ma è una logica molto simile).
    Si, in effetti con la mia SwitchForm è diventato semplicissimo perché come secondo parametro le passo (e.getModifiers() == 3) che significa che insieme al Ctrl è premuto anche lo Shift.
    Inoltre non avevo ancora affrontato la gestione delle form minimazzate che si risolve semplicemente con il setState(Frame.NORMAL) e toFront().

    Quindi grande ammirazione a te e un buon brindisi!
  • Re: [Risolto] Intercettare la combinazione di tasti <Ctrl><Tab>

    ZioCrick ha scritto:


    non avevo ancora scoperto l'uso dei KeyEvent.KEY_RELEASED .
    Sì, il ID dà il tipo dell'evento. E per i tasti ce ne sono 3: KEY_PRESSED, KEY_RELEASED e KEY_TYPED. Questo è il motivo per cui premendo e rilasciando un tasto hai almeno 2 eventi (appunto un pressed e poi un released). Poi per i tasti che rappresentano un carattere (lettere, numeri ...), c'è anche il typed.

    andbin ha scritto:


    Mi sembra di capire che serva a partire dalla form attiva, cosa che io ho risolto con l'argomento curForm della mia SwitchForm.
    Sicuramente la tua soluzione è più elegante.
    Ho ragionato così. Durante la esecuzione di una applicazione, a seconda di cosa/quanto mostra, l'array fornito da Frame.getFrames() PUÒ cambiare. Possono essercene di più ma anche di meno di frame elencati nell'array, ad esempio se un frame viene disposed e poi garbage collected.
    Quindi non ha senso tenersi da parte un indice nell'array e ha ancora meno senso tenersì l'array "precedente" o cose del genere.

    Semplicemente prima vado a ri-trovare il frame "attivo" e poi da questo cerco in avanti il primo frame che è "visible" (guarda il EDIT che ho fatto sopra).

    andbin ha scritto:


    come secondo parametro le passo (e.getModifiers() == 3) che significa che insieme al Ctrl è premuto anche lo Shift.
    Lo sai che c'è anche isShiftDown() ?
    La documentazione javadoc del framework la leggi? Io la leggo tutti i giorni e più/molte volte al giorno.

    EDIT: e comunque, e.getModifiers() == 3 è potenzialmente inappropriato (dipende da cosa si accetta di preciso)

    andbin ha scritto:


    Inoltre non avevo ancora affrontato la gestione delle form minimazzate che si risolve semplicemente con il setState(Frame.NORMAL) e toFront().
    Beh, prima ha senso riportare il frame in stato normale (se non lo è già) e poi riportarla in primo piano. Se non fai toFront() non riattivi un frame che invece è già visibile ma non attivo.
  • Re: [Risolto] Intercettare la combinazione di tasti <Ctrl><Tab>

    andbin ha scritto:


    Sì, il ID dà il tipo dell'evento. E per i tasti ce ne sono 3: KEY_PRESSED, KEY_RELEASED e KEY_TYPED. Questo è il motivo per cui premendo e rilasciando un tasto hai almeno 2 eventi (appunto un pressed e poi un released). Poi per i tasti che rappresentano un carattere (lettere, numeri ...), c'è anche il typed.
    Ah ecco! Ma allora non capisco perché nel caso dei 3 eventi il getKeyCode mi dava il valore ASCII solo per il primo e ultimo evento, mentre per quello di mezzo mi dava 0.
    Nell'esempio che avevo citato per la barra spaziatrice ottenevo la sequenza: 32, 0, 32.

    andbin ha scritto:


    Lo sai che c'è anche isShiftDown() ?
    Ah! Cuccato un'altra volta.

    andbin ha scritto:


    La documentazione javadoc del framework la leggi? Io la leggo tutti i giorni e più/molte volte al giorno.
    Ehm ... framework what?
    Questa? https://www.oracle.com/technetwork/java/index.htm
    No, siccome non sviluppo più per professione, non ho proprio il tempo di leggermi tomi in inglese.
    Cerco di fare ricerche mirate sul web, anche se poi le parti di documentazione che trovo (in inglese) mi risultano incomprensibili, un po perché sono in inglese, ma soprattutto perché usano una terminologia a me quasi completamente sconosciuta.
    Mi sto rendendo conto che il mondo Java e OOP è di una vastità e complessità impressionante!
    Avrei bisogno un buon libro in italiano, ma non che spiegasse solo i fondamenti, ma che spiegasse a cosa servono e come si usano tutte le classi e metodi etc. di java.
    Ma dovrebbe essere in formato elettronico in modo da fare ricerche sul PC, perché se devo consultarlo in formato cartaceo ci vogliono tempi biblici!
  • Re: [Risolto] Intercettare la combinazione di tasti <Ctrl><Tab>

    ZioCrick ha scritto:


    Ah ecco! Ma allora non capisco perché nel caso dei 3 eventi il getKeyCode mi dava il valore ASCII solo per il primo e ultimo evento, mentre per quello di mezzo mi dava 0.
    Nell'esempio che avevo citato per la barra spaziatrice ottenevo la sequenza: 32, 0, 32.
    Il getKeyCode() è valido solo per "pressed"/"released". Per il "typed", invece è valido il getKeyChar() perché getKeyCode() restituisce sempre VK_UNDEFINED (che vale 0). Tutto questo è ben documentato nel javadoc di KeyEvent.

    andbin ha scritto:


    Ehm ... framework what?
    Questa? https://www.oracle.com/technetwork/java/index.htm
    Quella è la pagina principale su Java di Oracle.

    No, io dico la documentazione della piattaforma Java SE (Standard Edition):
    https://docs.oracle.com/javase/8/docs

    e ancora più importante la documentazione "javadoc" del framework di Java SE:
    https://docs.oracle.com/javase/8/docs/api

    (i link sono per Java SE 8 ma ci sono anche le altre versioni più e meno recenti).

    Quest'ultima va consultata. Altrimenti ti garantisco che non si va molto avanti ...

    ZioCrick ha scritto:


    No, siccome non sviluppo più per professione, non ho proprio il tempo di leggermi tomi in inglese.
    Purtroppo in campo informatico/programmazione, l'inglese è necessario. E anche leggere la documentazione, anche se programmi solo per passione/hobby e non per professione.

    ZioCrick ha scritto:


    Avrei bisogno un buon libro in italiano, ma non che spiegasse solo i fondamenti, ma che spiegasse a cosa servono e come si usano tutte le classi e metodi etc. di java.
    In italiano, di buoni (ma non li conosco personalmente, sono molto citati sui forum), ci sono i libri di Claudio De Sio Cesari. Ma non so dire se c'è anche una edizione "elettronica".
  • Re: [Risolto] Intercettare la combinazione di tasti <Ctrl><Tab>

    Grazie ancora andbin per le preziose indicazioni.

    Mi sono salvato i link che mi hai riportato (relativi alla versione 7, che è quella che uso io ... spero ... visto che ho installata la 1.7.0_25) e vedrò di farne buon uso.



    PS: Si certo, l'inglese è vitale nel mondo informatico, infatti quando sviluppavo professionalmente mi leggevo un mucchio di materiale in inglese ... ma sempre in rete.
Devi accedere o registrarti per scrivere nel forum
12 risposte