Domanda Aiuto come riconoscere multi keypressed

Stato
Discussione chiusa ad ulteriori risposte.

supervanzo

Utente Bronze
9 Aprile 2014
37
12
1
49
Salve a tutti, ho un grande bisogno del vostro aiuto:
devo sviluppare un applicazione che simuli un tastierino numerico/alfabetico (per capirci quello dei vecchi telefonini senza T9), in cui la pressione di uno stesso tasto 1, 2 o 3 volte, genera la scrittura di un carattere diverso, al fine di scrivere una stringa.

ad esempio
tasto 1 = a ; 1 due volte = b ; 1 tre volte= c;
tasto 2 = d ; 2 due volte = e ; 2 tre volte= f;
ecc.

Nella classe principale ho implementato KeyListener per l'ascolto, per cui devo sviluppare il metodo KeyPressed.
Con il metodo riesco a catturare l'evento chiave di una sola pressione:
come posso implementare la cattura dell'evento di doppia e tripla pressione di un tasto?

Spero di essermi spiegato abbastanza bene.
Grazie in anticipo! :)
 
Ammetto che sto ancora pensando a una buona soluzione per questo problema. Me ne sono venute in mente alcune ma per ora niente di che.

Per ora la soluzione che ho in mente prevede l'utilizzo di Calendar (per recuperare i secondi), Timer e TimerTask per implementare una soluzione che resetti la stampa (un po' macchinosa, ho un'altra mezza idea più semplice).

Con un rapido controllo in keyPressed() puoi verificare se il tasto premuto è lo stesso della precedente volta e in tempo utile: in tal caso sarà il secondo valore quello selezionato.

Certo, per farlo bene richiede sicuramente del buon lavoro sotto. :p Questo è solo uno spunto, non so se ho il tempo per starci dietro. :p
 
Ammetto che sto ancora pensando a una buona soluzione per questo problema. Me ne sono venute in mente alcune ma per ora niente di che.

Per ora la soluzione che ho in mente prevede l'utilizzo di Calendar (per recuperare i secondi), Timer e TimerTask per implementare una soluzione che resetti la stampa (un po' macchinosa, ho un'altra mezza idea più semplice).

Con un rapido controllo in keyPressed() puoi verificare se il tasto premuto è lo stesso della precedente volta e in tempo utile: in tal caso sarà il secondo valore quello selezionato.

Certo, per farlo bene richiede sicuramente del buon lavoro sotto. :p Questo è solo uno spunto, non so se ho il tempo per starci dietro. :p
Grazie della risposta.
Avevo pensato anche io ad una cosa simile alla tua.
L'idea era quella di mantenere il tempo a partire dal primo Keypressed di un pulsante e, se si premeva entro un breve lasso di tempo, si passava al secondo valore e cosi' via per i successivi.
Solo che è abbastanza ingarbugliato da implementare e mi sembra strano che non esista qualche metodo o possibilità di farlo con meno complicazioni.
 
Guarda, a mio avviso il controllo del tempo è la parte più semplice perché hai già il listener pronto. ;) Alla fine basta un if con un paio di condizioni. Come per tutte le cose mi sono già scritto la mia soluzione ovviamente, solo che provo a darti un po' di idee prima di postarla. ;)

Quindi, in pseudocodice (se non l'hai mai visto può sembrare un po' ostico) qualcosa del genere:
Codice:
IF isSameKey(oldKey, pressedKey) AND inTime(oldSeconds, currentSeconds)
    updateLabel()
    pressCount <- (pressCount + 1) % 3
ELSE
    pressCount <- 0
    oldKey <- pressedKey
    updateLabel()

/* pressCount save the information about the selected letter in the same button */
O almeno, la traduzione della mia attuale implementazione per quanto riguarda il listener. :) E rimangono dal implementare (o comunque riscrivere) le tre funzioni.
 
  • Mi piace
Reazioni: supervanzo
Ok, dunque, dimmi se ho capito bene:
- isSameKey, dovrei andare a confrontare l'ultimo tasto premuto (salvato in qualche variabile) con quello appena premuto. E ci siamo.
- pressCount, è una variabile che mi conta quante volte premo lo stesso pulsante ( si azzera quando è diverso). E ci siamo.
- inTime è un po' più ostico: dovrei leggere il tempo al momento della pressione del tasto, mantenerlo e poi confrontarlo con il successivo. Solo che deve rientrare in un range di tempo massimo. Come posso farlo?
 
Ok, dunque, dimmi se ho capito bene:
- isSameKey, dovrei andare a confrontare l'ultimo tasto premuto (salvato in qualche variabile) con quello appena premuto. E ci siamo.
- pressCount, è una variabile che mi conta quante volte premo lo stesso pulsante ( si azzera quando è diverso). E ci siamo.
- inTime è un po' più ostico: dovrei leggere il tempo al momento della pressione del tasto, mantenerlo e poi confrontarlo con il successivo. Solo che deve rientrare in un range di tempo massimo. Come posso farlo?
Tutto perfetto. Per recuperare i secondi ci sono diversi metodi. Personalmente ho adottato una soluzione di questo tipo:
PHP:
import java.text.SimpleDateFormat;
import java.util.Calendar;

/* some code here */

private SimpleDateFormat sdf = new SimpleDateFormat("ss");

/* other code */

/**
  * Retrieve current time in seconds
  *
  * @return current seconds
  */
private int getSeconds() {
    return Integer.parseInt(sdf.format(Calendar.getInstance().getTime()));
}
A questo punto puoi procedere come col il codice del pulsante premuto e usare i secondi a piacimento per il tempo a disposizione.
 
Quindi userei l'orario del momento in cui clicco, ho capito.
E se invece a partire da quel momento facessi partire un timer: esiste una funzione che conta il tempo?
Potrei semplicemente verificare se non è arrivato a zero, per poi riavviarlo.
Che ne pensi?
 
Penso che fosse la mia prima implementazione. :p Solo che scrissi il codice di fretta e trovai più semplice contare direttamente i secondi. Ora che ho potuto rivedere meglio la cosa direi che è molto più pulito fare tutto con le classi Timer e TimerTask, che comunque già prima utilizzavo.

Il problema sta nel sincronizzare bene le cose: ammetto che le nozioni di Sistemi Operativi riguardo ai semafori qui hanno fatto comodo. ;)

Il problema è che ogni timer che avvi continua la sua esecuzione per conto suo. Devi usare quindi un contatore che ti permetta di capire quando l'ultimo timer avviato ha finito la sua esecuzione.

Supponiamo che quando aliveTimers arrivi a zero non ci siano più timer attivi e quindi il tempo sia scaduto. In pseudo codice semplificato:
Codice:
function keyPressed()
    IF isSameKey() && aliveTimers > 0
        aliveTimers <- aliveTimers + 1 // We have activated a new timer
    ELSE
         aliveTimers <- 1
   
     setTimer(seconds)


class timer()
    IF aliveTimers > 0  // Decrement only if the variable is positive
        aliveTimers <- aliveTimers - 1

    IF aliveTimers == 0  // There aren't active timers
        waitingMode()

Visto che mi ritengo abbastanza soddisfatto dell'implementazione unito al fatto che tra stasera e domani potrei avere poco tempo, ti lascio quello che ho scritto io: T9.java. Ovviamente prima vedi se riesci a scrivere già qualcosa da solo. ;)
 
Innanzitutto grazi mille per l'aiuto. E' per un progetto dell'università, quindi mi stai salvando.
Allora ho cercato di capire al meglio la classe da te creata per adattarla al meglio alla mia.
Diciamo che funziona, ma sto combattendo contro un problemino:se premo 2/3 volte il tasto lo riconosce, ma stampa anche la prima lettera e la seconda.
es. premo 2 volte il tasto 1:
prima pressione---> stampa 'a'
seconda pressione---> stampa 'b'
Volevo far in modo che se premo due volte mi stampi SOLO la 'b'. Sto pastrocchiando ma non risco a trovare una soluzione.

Pensandoci credo si potrebbe risolvere facendo in modo che la scrittura avvenga solo quando il timer è terminato, ma non ho idea di come implementarlo evitando che la pressione sia riconosciuta come scrittura.
Cosa mi consigli?
 
Come previsto purtroppo sono stato impegnato e pure tutto oggi pomeriggio. :p Comunque, ho lavorato sul codice che avevo scritto io per motivi di praticità e tempo a disposizione. Ora salva l'ultimo tasto premuto. Ho fatto pochi test ma sembra funzionare.

In pratica mi salvo, al momento della chiamata del timer, tasto (e counter). Se allo scadere sono sempre gli stessi allora stampo. Ora che ci penso mancherebbe il fatto che se il tasto è diverso non scrive subito quello precedente... Forse richiederebbe una veloce rivisitazione della logica ma temo di non avere troppo tempo stasera.

In ogni caso ho aggiornato: T9.java.
 
In effetti mi funziona tutto, ma l'inconveniente è proprio la stampa multipla.
Sto provando a mettere un flag che diventa vero solo quando il tempo di attesa è finito, per cui non dovrebbe stampare prima che diventi true, ma qualcosa non quadra nella logica, perchè continua a far come vuole :)
Dove lo metteresti?
 
Perdona il ritardo ma questa settimana sono stato parecchio impegnato e non ho potuto dedicarmici molto. So che eri di fretta e spero quindi che tu sia riuscito comunque a trovare una buona soluzione. :)

Comunque stamattina ho avuto del tempo libero e ho aggiornato il progetto, ora gestisce tutto correttamente mi pare. ;)
Comprendo che la logica sia un po' intricata magari e andrebbe studiato il funzionamento un po'.
 
Salve a tutti, ho un grande bisogno del vostro aiuto:
devo sviluppare un applicazione che simuli un tastierino numerico/alfabetico (per capirci quello dei vecchi telefonini senza T9), in cui la pressione di uno stesso tasto 1, 2 o 3 volte, genera la scrittura di un carattere diverso, al fine di scrivere una stringa.

ad esempio
tasto 1 = a ; 1 due volte = b ; 1 tre volte= c;
tasto 2 = d ; 2 due volte = e ; 2 tre volte= f;
ecc.

Nella classe principale ho implementato KeyListener per l'ascolto, per cui devo sviluppare il metodo KeyPressed.
Con il metodo riesco a catturare l'evento chiave di una sola pressione:
come posso implementare la cattura dell'evento di doppia e tripla pressione di un tasto?

Spero di essermi spiegato abbastanza bene.
Grazie in anticipo! :)

parte già da un idea sbagliata di fondo , tu devi lavorare su due metodi :
void KeyPressed(KeyEvent e)
void KeyReleased(KeyEvent e)
Presumendo che ogni tasto abbia la sua lista di scelta (tipo 1 ha una lista associata che avrà solo abc)
ora quando premi devi fare una cosa estremamente semplice all'evento KeyPressed porti avanti di uno la lettera.
Altro punto la durata, sul vecchio t9 per avanzare di una lettere dovevi essere veloce,altrimenti lasciava quella lettera ... ecco perché devi implementare uno StepWatch (puoi usare anche la classe System,inutile scomodare Java.Util)
Codice:
//int mypos=0;
StepWatch c1;
void KeyPressed(KeyEvent e){
mystep.start();
++mypos; //se ho premuto incremento di uno


}

void KeyReleased(KeyEvent e){
mystep.stop();

if (c1.getTime()>70) // vuol dire che è passato molto tra pressione è rilascio , i valori sono a caso eh considera che devi lavorare in secondi
{
getTasto(mypos); //stampo il tasto
mypos=0; //riazzero posizione button
}
//altrimenti è passato poco tra un rilascio e l'altro e quindi c'è possibilità che posso andare ancora avanti
}

A questo punto secondo questa metodologia ogni tasto sarà un oggetto e quindi devi creare una classe che presenta come attributi :
- lista dei tasti
-contatore posizione
 
  • Mi piace
Reazioni: Scanetatore
Stato
Discussione chiusa ad ulteriori risposte.