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
}