View Full Version : Problema con un Timer [Java]
superburp
21-03-2007, 22:09
Ciao a tutti, sono nuovo di questo forum.
Scrivo perchè ho un problema con un programma da fare con Java. Ho realizzato un programma che fa visualizzare su una porzione di una tastiera di un pianoforte 4 accordi e con la possibilità di creare un accordo cliccando sui vari tasti (con un ovvio limite per il numero di tasti schiacciabili).
Ora vorrei mettere un timer per visualizzare i 4 accordi uno dopo l'altro ad un intervallo di tempo predefinito (ad esempio 2 secondi). Come posso fare? Ho provato a creare un listener, ma sono sicuro che sia sbagliato.
Lo riporto qui, così se qualcuno gentilmente volesse aiutarmi mi farebbe un gran piacere.
import javax.swing.timer;
public class ListenerTimer implements ActionListener {
private PannelloGrafico pannGraf;
public Timer t;
public ListenerTimer (PannelloGrafico pannGraf) {
this.pannGraf = pannGraf;
}
int delay = 1500; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed (ActionEvent e) {
t= new Timer (1500);
t.start();
if (t=0) {
accordoDo=true;
accordoLa=false;
accordoRe=false;
accordoSol=false;
}
if (t=1500) {
accordoLa=true;
accordoDo=false;
accordoRe=false;
accordoSol=false;
}
if (t=3000) {
accordoRe=true;
accordoDo=false;
accordoLa=false;
accordoSol=false;
}
if (t=4500) {
accordoSol=true;
accordoDo=false;
accordoLa=false;
accordoRe=false;
}
setRepeats (false);
}
}
}
P.S.: Ho usato i colori per cercare di rendere più chiara la struttura, chè altrimenti non so come fare per mantenere gli spazi.
t e' un Timer, non puo' essere =0, =1500, ecc.
E' mooolto piu' semplice:
Timer timer = new Timer( delay, new ActionListener() {
public void actionPerformed(ActionEvent e)
{
// qui metti cosa vuoi eseguire ogni 'delay' msec
} });
timer.start();
Poi ti servira' qualche meccanismo, tipo una lista con i 4 accordi da\
impostare uno dopo l'altro.
superburp
22-03-2007, 13:05
E per mettere le azioni vanno bene i true e false che ho messo? Oppure c'è un altro modo? Grazie comunque.
superburp
22-03-2007, 16:20
Allora, ho provato a fare come hai detto, ma mi dà più di un problema. Sicuramente sbaglio ancora.
Ho tolto la parte su if t=0, t=1500, ecc., ma non capisco come fare per dare i comando per gli accordi. Non è che mi potresti dire dove mettere quella parte Timer= new Timer ecc.?
Ma hai gia' fatto il resto del programma?
Comunque dipende, lo puoi mettere nel costruttore del pannello,
ad esempio, e farlo partire in un listener.
Per quanto riguarda tutti quei boolean, non sono il massimo, servirebbe
ad es. un oggetto Accordo (meglio una enum), ma poi dovresti in qualche
modo visualizzarlo.
P.S.: Ho usato i colori per cercare di rendere più chiara la struttura, chè altrimenti non so come fare per mantenere gli spazi.
Basta che racchiudi il codice nel blocco "CODE".
superburp
23-03-2007, 18:22
Ma hai gia' fatto il resto del programma?
Comunque dipende, lo puoi mettere nel costruttore del pannello,
ad esempio, e farlo partire in un listener.
Per quanto riguarda tutti quei boolean, non sono il massimo, servirebbe
ad es. un oggetto Accordo (meglio una enum), ma poi dovresti in qualche
modo visualizzarlo.
Sì, il resto del programma è fatto; se volete lo posso allegare. Comunque quello che vorrei fare è proprio metterlo nel costruttore e farlo partire in un listener.
P.S.: Lo allego, per chi gli volesse dare un'occhiata.
superburp
23-03-2007, 18:28
Basta che racchiudi il codice nel blocco "CODE".
Fatto, grazie per il consiglio.
superburp
27-03-2007, 23:39
Ho fatto delle modifiche in base a quanto mi è stato detto all'università dall'assistente. Ho fatto un listener con l'avvio del timer:
import javax.swing.Timer;
public class ListenerTimer implements ActionListener {
private Timer t = new Timer (delay, new ActionListener());
private int delay=1500;
private PannelloGrafico pannGraf;
public ListenerTimer (PannelloGrafico pannGraf) {
this.pannGraf = pannGraf;
}
pannGraf.t.start();
A questo punto mi hanno detto che dovrei fare un listener a parte dove mettere la visualizzazione ciclica degli accordi.
Ho provato a fare una cosa del genere, ma mi dà errore (chiede sempre un ; alla riga del for):
public class ListenerCiclo implements ActionListener {
private PannelloGrafico pannGraf;
private int ciclo;
public ListenerCiclo (PannelloGrafico pannGraf) {
this.pannGraf = pannGraf;
}
public void actionPerformed (ActionEvent e) {
for (double pannGraf.ciclo=1; pannGraf.ciclo<4; pannGraf.ciclo++){
pannGraf.disegnaDo =true;
}
}
}
Dove sbaglio?
for (double pannGraf.ciclo=1; pannGraf.ciclo<4; pannGraf.ciclo++)
In Java il punto (.) non è un carattere che può far parte del nome di una variabile.
Nel tuo caso, il nome "tentato" è pannGraf.ciclo. E' una dichiarazione perchè è preceduta dal nome di un tipo nel segmento di inizializzazione del ciclo for:
for(double pannGraf.ciclo <- dichiarazione, punto, ahiahaihahai!
Il compilatore ti dice che manca un punto e virgola perchè se dicesse subito dove sta il problema a programmare sarebbero buoni tutti. Non sia mai! :D.
La soluzione al problema dipende da quello che avresti voluto dire, che hai detto e che il compilatore non ha capito.
E' possibile che tu voglia riferirti ad un campo pubblico di nome ciclo e tipo :> int, dichiarato per le istanze di PannelloGrafico. In questo caso la forma sarebbe:
for(pannGraf.ciclo = 1; pannGraf.ciclo < 4; pannGraf.ciclo++) {
pannGraf.disegnaDo = true;
}
Che è sintatticamente corretto ma lascia un po' perplessi: potresti non ottenere il risultato voluto.
superburp
03-04-2007, 22:05
Allora, ci sono stati dei cambiamenti. Il concetto alla base del timer l'ho capito all'incirca, però ho dei problemi nella realizzazione pratica.
Per realizzare il timer ho inserito nel file del pannello grafico queste variabili:
int noteCiclo;
ActionListener evento = new ActionListener ();
private Timer t = new Timer (delay, evento);
int delay=1500;
Mi dà come errore "cannot find symbol class ActionListener" e "illegal forward reference" (riferito alla riga private Timer t).
Ho poi inserito, sempre nel file, una classe riferita all'evento:
public void actionPerformed (ActionListener evento) {
if (noteCiclo == 3) {
accordoDo=true;
accordoLa=false;
accordoRe=false;
accordoSol=false;
noteCiclo++;
}
if (noteCiclo == 2) {
accordoLa=true;
accordoDo=false;
accordoRe=false;
accordoSol=false;
noteCiclo++;
}
if (noteCiclo == 1) {
accordoRe=true;
accordoDo=false;
accordoLa=false;
accordoSol=false;
noteCiclo++;
}
if (noteCiclo == 0) {
accordoSol=true;
accordoDo=false;
accordoRe=false;
accordoLa=false;
noteCiclo++;
}
}
E' corretta? Dovrebbe far visualizzare i 4 accordi ciclicamente.
A parte gli errori visti in precedenza, nel complesso va bene? Dove devo mettere i comandi t.start (); e t.stop();? Il primo ho pensato dopo il delay, l'altro alla fine della classe del ciclo. E' giusto?
Ehm... non offenderti, ma ti mancano proprio le basi di java, forse sarebbe opportuno
che cominciassi con programmini piu' semplici...
In ogni caso:
Allora, ci sono stati dei cambiamenti. Il concetto alla base del timer l'ho capito all'incirca, però ho dei problemi nella realizzazione pratica.
Per realizzare il timer ho inserito nel file del pannello grafico queste variabili:
int noteCiclo;
ActionListener evento = new ActionListener ();
private Timer t = new Timer (delay, evento);
int delay=1500;
Mi dà come errore "cannot find symbol class ActionListener" e "illegal forward reference" (riferito alla riga private Timer t).
Non puoi instanziare un ActionListener, e' un'interfaccia.
E non puoi usare delay finche' non l'hai dichiarato, quindi devi scambiare le ultime due linee.
Ho poi inserito, sempre nel file, una classe riferita all'evento:
public void actionPerformed (ActionListener evento) {
if (noteCiclo == 3) {
accordoDo=true;
accordoLa=false;
accordoRe=false;
accordoSol=false;
noteCiclo++;
}
if (noteCiclo == 2) {
accordoLa=true;
accordoDo=false;
accordoRe=false;
accordoSol=false;
noteCiclo++;
}
if (noteCiclo == 1) {
accordoRe=true;
accordoDo=false;
accordoLa=false;
accordoSol=false;
noteCiclo++;
}
if (noteCiclo == 0) {
accordoSol=true;
accordoDo=false;
accordoRe=false;
accordoLa=false;
noteCiclo++;
}
}
E' corretta? Dovrebbe far visualizzare i 4 accordi ciclicamente.
A parte gli errori visti in precedenza, nel complesso va bene? Dove devo mettere i comandi t.start (); e t.stop();? Il primo ho pensato dopo il delay, l'altro alla fine della classe del ciclo. E' giusto?
Quel codice non visualizza niente, setta solo delle variabili in memoria.
Lo fai partire quando ti serve...
superburp
04-04-2007, 15:36
Ehm... non offenderti, ma ti mancano proprio le basi di java, forse sarebbe opportuno
che cominciassi con programmini piu' semplici...
In ogni caso:
Non puoi instanziare un ActionListener, e' un'interfaccia.
E non puoi usare delay finche' non l'hai dichiarato, quindi devi scambiare le ultime due linee.
Quel codice non visualizza niente, setta solo delle variabili in memoria.
Lo fai partire quando ti serve...
Non mi offendo, anzi, lo so bene. Purtroppo non l'ho scelto io il programma...
Comunque, mi potresti dire come fare per instanziare l'ActionListener?
Sul codice un amico mi ha detto che dovrebbe in questo modo far vedere gli accordi per un ciclo soltanto (che poi è quello che mi interessa). Dici che non serve neanche a questo?
Grazie comunque per la risposta.
Comunque, mi potresti dire come fare per instanziare l'ActionListener?
Devi implementare l'interfaccia, come ad esempio hai fatto sopra con
la classe ListenerCiclo, o con una classe anonima, come ti ho
mostrato nel primo esempio che ti ho fatto.
Sul codice un amico mi ha detto che dovrebbe in questo modo far vedere gli accordi per un ciclo soltanto (che poi è quello che mi interessa). Dici che non serve neanche a questo?
Non riesco a capire, quando fai accordoDo = true; eccetera, non fai altro
che impostare delle variabili, per visualizzare questi accordi devi "disegnare",
anche solo aggiungendo delle JLabel a cui cambi il colore di sfondo...
Non ti posso aiutare di più, dovrei scriverti tutto il programma... :boh:
superburp
04-04-2007, 18:54
Devi implementare l'interfaccia, come ad esempio hai fatto sopra con
la classe ListenerCiclo, o con una classe anonima, come ti ho
mostrato nel primo esempio che ti ho fatto.
Non riesco a capire, quando fai accordoDo = true; eccetera, non fai altro
che impostare delle variabili, per visualizzare questi accordi devi "disegnare",
anche solo aggiungendo delle JLabel a cui cambi il colore di sfondo...
Non ti posso aiutare di più, dovrei scriverti tutto il programma... :boh:
I disegni degli accordi già ci sono, il resto del programma è fatto. Manca di mettere la possibilità di vedere i 4 accordi ciclicamente. Grazie comunque.
Senza vedere il codice che imposta l'accordo è impossibile aiutarti...
Immagino che sia un metodo, impostare una variabile booleana
non fa niente - a meno che poi questa variabile sia usata da qualche
altra parte.
Facciamo un esempio. E di solito quando uno dice così finisce tutto a schifìo :D.
E' scritto in fretta, quindi ci sono un po' di faccende in sospeso. Ma l'idea dovrebbe trasparire. C'è una tastiera con 4 tasti. La tastiera ha un metodo, setAccordi, che consente di attivare o disattivare i quattro tasti.
C'è un Timer incorporato in Sequence player che, a intervalli di tot millisecondi, chiama il metodo setAccordi della tastiera.
Gli accordi da usare per attivare/disattivare i tasti sono incorporati in un oggetto Sequence. Questa sequenza di accordi viene data in pasto al sequence player prima di invocare il suo metodo "play". Quando si preme "play", il SequencePlayer legge la sequenza e applica ogni volta il gruppo di accordi successivo alla tastiera.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class Main {
private Tastiera tastiera = new Tastiera();
private SequencePlayer player = new SequencePlayer(tastiera);
public void start() {
Sequence sequence = new Sequence();
sequence.push(Tastiera.DO + Tastiera.RE);
sequence.push(Tastiera.DO + Tastiera.FA);
sequence.push(Tastiera.MI + Tastiera.FA);
sequence.push(Tastiera.RE + Tastiera.MI);
player.setSequenza(sequence, 2000);
JButton button = new JButton("play");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
player.play();
}
});
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
buttonPanel.add(button);
JFrame window = new JFrame();
window.add(tastiera.getJComponent(), BorderLayout.CENTER);
window.add(buttonPanel, BorderLayout.SOUTH);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //brutalone
window.pack();
window.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Main().start();
}
});
}
}
class Sequence {
private LinkedList<Integer> data = new LinkedList<Integer>();
private int accordoCorrente;
public void push(int mascheraAccordi) {
data.add(mascheraAccordi);
}
public boolean sequenzaTerminata() {
return accordoCorrente == data.size();
}
public int getProssimoAccordo() {
return data.get(accordoCorrente++);
}
}
class SequencePlayer {
private ActionListener jumper = new ActionListener() {
public void actionPerformed(ActionEvent e) {
applicaAccordoSuccessivo();
}
};
private javax.swing.Timer timer = new javax.swing.Timer(0, jumper);
private Sequence sequenza;
private Tastiera tastiera;
public SequencePlayer(Tastiera t) {
tastiera = t;
}
public void setSequenza(Sequence s, int tempo) {
sequenza = s;
timer.setDelay(tempo);
}
public void play() {
timer.start();
}
public void stop() {
timer.stop();
}
private void applicaAccordoSuccessivo() {
if(sequenza == null || sequenza.sequenzaTerminata()) {
tastiera.setAccordi(Tastiera.NESSUNO);
stop();
} else {
tastiera.setAccordi(sequenza.getProssimoAccordo());
}
}
}
class Tastiera {
public static final int NESSUNO = 0;
public static final int DO = 2;
public static final int RE = 4;
public static final int MI = 8;
public static final int FA = 16;
private JToggleButton doButton = new JToggleButton("DO");
private JToggleButton reButton = new JToggleButton("RE");
private JToggleButton miButton = new JToggleButton("MI");
private JToggleButton faButton = new JToggleButton("FA");
private JComponent component;
public Tastiera() {
JPanel panel = new JPanel(new GridLayout(1, 4));
pushAndSet(panel, doButton, reButton, miButton, faButton);
component = panel;
}
public JComponent getJComponent() {
return component;
}
public void setAccordi(int maschera) {
doButton.setSelected(èAttivo(DO, maschera));
reButton.setSelected(èAttivo(RE, maschera));
miButton.setSelected(èAttivo(MI, maschera));
faButton.setSelected(èAttivo(FA, maschera));
}
private void pushAndSet(Container container, JComponent...components) {
Dimension size = new Dimension(32, 64);
for(JComponent c : components) {
c.setPreferredSize(size);
c.setBorder(BorderFactory.createLineBorder(Color.BLACK));
container.add(c);
}
}
private boolean èAttivo(int accordo, int maschera) {
return (maschera & accordo) == accordo;
}
}
Non è detto che tu possa applicare questo modello alla tua applicazione. Essendo praticamente già scritta è possibile che tu debba trasformarla in qualcosa di più compatibile. Comunque spero dia un'idea circa l'uso di un timer nel contesto da te descritto.
superburp
05-04-2007, 20:28
Allora, intanto ringrazio tutti per la disponibilità. Poi aggiungo che forse quasi ci sono...
Il problema che ho sta nel modo per fargli visualizzare gli accordi. Il timer però funziona, perchè mettendo una riga System.out.println ("Ciao") compaiono le 4scritte nella finestra del prompt alla distanza impostata dal delay.
Vado con ordine. Nel file Pianforte (dove c'è il main) ho messo questo richiamo ad un listener chiamato Ciclo per quando si clicca su "Visualizzazione ciclica":
JMenuItem menu4di1=new JMenuItem ("Visualizzazione ciclica");
menu1.add(menu4di1);
menu4di1.addActionListener (new Ciclo (pannGraf));
Questo Ciclo è così fatto:
import java.awt.event.*;
public class Ciclo implements ActionListener {
private PannelloGrafico pannGraf;
public Ciclo (PannelloGrafico pannGraf) {
this.pannGraf = pannGraf;
}
public void actionPerformed (ActionEvent e) {
pannGraf.t.start();
}
}
Il Ciclo fa partire un timer definito nel pannello grafico in questo modo:
public int noteCiclo=0;
public ListenerCiclo evento = new ListenerCiclo(this);
public static int delay=1500;
public Timer t = new Timer (delay, evento);
Qui vengono introdotte la variabile noteCiclo che viene utilizzata nel ListenerCiclo che è così fatto:
import java.awt.event.*;
import javax.swing.Timer;
public class ListenerCiclo implements ActionListener {
private PannelloGrafico pannGraf;
public ListenerCiclo (PannelloGrafico pannGraf) {
this.pannGraf = pannGraf;
}
public void actionPerformed (ActionEvent e) {
if (pannGraf.noteCiclo == 3) {
pannGraf.accordoDo=true;
pannGraf.accordoLa=false;
pannGraf.accordoRe=false;
pannGraf.accordoSol=false;
pannGraf.noteCiclo++;
}
if (pannGraf.noteCiclo == 2) {
pannGraf.accordoLa=true;
pannGraf.accordoDo=false;
pannGraf.accordoRe=false;
pannGraf.accordoSol=false;
pannGraf.noteCiclo++;
}
if (pannGraf.noteCiclo == 1) {
pannGraf.accordoRe=true;
pannGraf.accordoDo=false;
pannGraf.accordoLa=false;
pannGraf.accordoSol=false;
pannGraf.noteCiclo++;
}
if (pannGraf.noteCiclo == 0) {
pannGraf.accordoSol=true;
pannGraf.accordoDo=false;
pannGraf.accordoRe=false;
pannGraf.accordoLa=false;
pannGraf.noteCiclo++;
}
if (pannGraf.noteCiclo == 4) {
pannGraf.t.stop();
}
}
}
Come ho già detto la parte grafica dei 4 accordi è fatta, si tratta di far sì che quando parte il timer li visualizzi ciclicamente, così come scrive "Ciao". Se questo metodo con true e false non è corretto come dovrei fare?
P.S.: Ho usato il metodo con true e false perchè nel anche pannello grafico ho fatto così.
superburp
06-04-2007, 16:35
Stavo pensando che forse potrei eliminare il listener Ciclo mettendo il comando pannGraf.t.start() nel ListenerCiclo e modificando la riga del file Pianoforte da menu4di1.addActionListener (new Ciclo (pannGraf)) in menu4di1.addActionListener (new :ListenerCiclo (pannGraf)).
superburp
06-04-2007, 20:46
Allora, facendo questa modifica effettivamente il programma funziona ancora.
Il problema che avevo per la visualizzazione era dovuto al fatto che al termine di ogni if del ListenerCiclo non mettevo il repaint(). L'ultimo problema che rimane è come fare per far sì che ogni volta che clicco su Visualizzazione ciclica parta il ciclo? Perchè così lo fa solo una volta, se riclicco non fa nulla.
superburp
06-04-2007, 21:01
Risolto anche questo, grazie a tutti per l'aiuto, il lavoro è finito :D!
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.