View Full Version : Due cosette in java
shadylane
26-07-2003, 08:38
Ho bisogno di sapere, magari anche con esempi di codice, come si fa a:
1) abilitare un pannello o il suo contenuto soltanto quando seleziono un determinato oggetto checkbox, mi spiego meglio.Ho un pannello che contiene dei checkbox, e vorrei che selezionando 2 di questi si abiliti la scrittura in delle textarea successive, inserite in un altro pannello, un po' come quando si installano dei programmi, che non si abilita il pulsante avanti finche non sei daccordo con la licenza.
2) prendere dei dati dalle textarea, salvarli in un file, poi rileggere il file e caricare i dati salvati al posto giusto.
Grazie e ciao.
1)
Il Pannello in cui sono le JCheckBox deve implementare ActionListener e bisogna aggiungerlo come Listener delle checkBox. Quando arriva un ActionEvent controlli se le 2 checkbox che ti interesano sono selezionate e in questo caso abiliti la JTextArea, di cui devi avere un riferimento nel pannelllo, esempio:
....class MyPanel extends JPanel implements ActionListener{
.
.
.
....JCheckBox box1...
....JCheckBox box2...
....JTextArea area....//Questo campo deve essere inizializzato
................................//col riferimento alla textArea ad esempio
...............................//nel costruttore
....public MyPanel(){
.
.
.
........box1.addActionListener(this);
........box1.addActionListener(this);
.
.
....}
....public void ActionPerformed(ActionEvent e){
........Object o = e.getSource();
........if((o == box1) || (o == box2)){
............if((box1.isSelected()) && (box2.isSelected()))
................area.setEnebled(true);
............else
.................area.setEnebled(false);
............return;
............;
........}
....}
.
.
.
}
shadylane
26-07-2003, 14:02
credo di aver capito, grazie mille
shadylane
28-07-2003, 17:08
Allora, rieccomi qui: mi da errore quando "abilito" l'action listener per i checkbox.
Ecco l'errore: C:\Programmi\Xinox Software\JCreator LE\MyProjects\SerialDemo.java:115: cannot resolve symbol symbol : method addActionListener (SerialDemo) location: class java.awt.Checkbox c1.addActionListener(this);
ED ecco il codice incriminato:
c1.addActionListener(this); c2.addActionListener(this);c3.addActionListener(this); c4.addActionListener(this);c5.addActionListener(this);c6.addActionListener(this); c7.addActionListener(this);
Il programma è impostato in questo modo: nel primo pannello in alto ci sono i checkbox, se ne scelgo 2 (separatamente, non in contemporanea) si devono attivare delle TextArea, che però vengono istanziate in un'altra classe. Infine ho nell'ultimo pannello un bottone e modificandogli l'azione lui riesce a settare ineditabili le textArea. Quindi escluderei un problema dovuto al fatto che si trovino in diversi pannelli.
Ho provato anche a mettere un itemListener ma non va (o forse ho sbagliato qualcos'altro).
Come risolvo?
Ciò che ti ho detto io vale per le classi del package javax.swing mentre tu hai usato l'awt, le classi del javax.swing (che ti consiglio di usare) hanno lo stesso nome delle corrispondenti classi awt, salvo una "J" iniziale, cosi devi scrivere:
JCheckBox box = new JCheckBox();.....
In particolare devi importare i seguenti package:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
Il metodo addActionListener non è infatti un metodo della classe CheckBox, ma è invece un metodo di JCheckBox. Per maggiori informazioni sulle classi del javx.swing ti indico la pagina della documentazione del sito della sun http://java.sun.com/j2se/1.4.2/docs/api/index.html, ad ogni modo se hai altri problemi scrivi pure.
Ciao.
shadylane
28-07-2003, 18:57
La documentazione java l'ho scaricata tutta, ed infatti per le checkbox non ho trovato l'actionlistener.
Ora provo a mettere la j davanti.
Ancora grazie
shadylane
28-07-2003, 19:19
Allora, ho guardato i JCheckBox, ed anche i JRadioButton, e se non sbaglio bisogna creare un pannello specifico per loro, con relativo bordo, giusto?
Io per prova li ho messi al posto dei vecchi CheckBox, con le opportune modifiche (ho tolto il CheckBoxGroup) ma l'actionListener sembra non funzionare (serve obbligatoriamente un contenitore?) Inoltre ho visto che è possibile selezionare più di un elemento alla volta, ed io li vorrei esclusivi, dipende sempre dal contenitore?
shadylane
28-07-2003, 19:27
Dimenticavo una cosa, spero non sia importante: io ho già implementato un actionPerformed, per un bottone e per i menu, può questo influenzare il checkbox?
shadylane
30-07-2003, 11:44
un uppino per me :)
Originariamente inviato da shadylane
Dimenticavo una cosa, spero non sia importante: io ho già implementato un actionPerformed, per un bottone e per i menu, può questo influenzare il checkbox?
Cosa intendi x influenzare?? Se nel codice dell''ActionPerformed associato al bottone e ai menu intervieni direttamente sulla JCheckBox allora si.
Ma se non aggiungi il listener esplicitamente ad un oggetto (in questo caso le CheckBox), non c'è verso di influenzarle!!
shadylane
30-07-2003, 14:11
Per influenzarle intendo:
il mio bottone deve fare una cosa, le checkbox un'altra, se le metto tutte nell'actionlistener ho dei problemi, per cui devo usare un itemchanged, oppure no?
Cmq ora ho trovato un esempio in cui i checkbox hanno gli itemstatechanged, provo ad usare quelli.
Puoi individuare la sorgente dell'evento applicando il metodo getSource() all'evento stesso...
public void actionPerformed(ActionEvent e) {
if (e.getSource() == bottone){
...
}
else if(e.getSource() == checkbox){
...
}
}
shadylane
30-07-2003, 16:09
Grazie mille.
Avevo provato anche creando un'altra classe, adesso vedo qual'è meglio.
Puoi anche, per ogni oggetto, scrivere un codice del genere:
oggetto1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
.....;
}
});
oggetto2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
.....;
}
});
Io personalmente trovo molto comoda questa soluzione...
shadylane
30-07-2003, 16:23
Siccome ho molte checkbox è meglio fare un lavoro unico e più generale, altrimenti dovrei ripetere troppo codice.
Cmq lo terrò presente per il futuro.
Grazie mille
shadylane
30-07-2003, 17:03
Problema 1 risolto, ora c'è il problema 2
come faccio a salvare il contenuto della text area in un file e poi ricaricarlo?
Giuro che poi non rompo più. (spero) :sofico:
Bhè per qusto problema ti vai a leggere un quyalunque tutorial alla voce "Utilizzo dei file", o se hai un minimo di pratica basta la doc delle API (classe File)
shadylane
31-07-2003, 12:42
Risolto anche quello, con le properties.
Ora sto mettendo a posto i dettagli.
Come faccio ad avere tutto il programma dello stesso colore? Il bottone del menù è bianco, mentre la barra è grigia, non trovo nessun setColor o simili. :confused:
shadylane
31-07-2003, 15:36
Finito tutto, qualcuno ci vuole dare un'occhiata, e dirmi se ho fatto delle stupidate (soprattutto nei commenti)??
shadylane
05-08-2003, 19:54
Nessuno vuol fare il correttore di bozze? :D
Dai che vi dedico l'esame!!
C'è un lapsus (che forse hai già corretto, perchè nel codice postato è impossibile che salvi) alla linea 329 (+o-) fileOut(nomefile + nomedirectory) ->> fileOut(nomedirectory + nomefile). Usando un FileOutputStream potresti direttamente fare "fileOut(fd.getFile())" con "if (fd.getFile()!=null)" alla 310, risparmi un "&&" e non fa mai male.
Nel complesso direi che è ok, molto dipende da quello che si aspetta il (professore?) a cui devi mostrarlo (se no ho capito male è un esercizio)...solo che è lungo come la fame! :) . Ci sono una paio di bizzarrie, un metodo deprecated, spezzerei l'applicazione in 2 o 3 classi anzichè un megamalloppone da 500 linee, il layout non resisterebbe ad un maniaco del ridimensionamento (prova a rendere il frame un pò più piccolo, le etichette perdono pezzi), se non hai tempo taglia la testa al toro e usa setResizable(false) per "wan".
Quei 10 TextField non puoi infilarli in un array? Se li inizializzi in un ciclo tra reset e inizializzazione risparmi 15 linee e Dio sa quanti caratteri.
Lo stesso vale per i Label
Non toccare il save, l'idea di usare un Properties è elegante, ti darei un 30 solo per quella :D
shadylane
06-08-2003, 17:31
Grazie mille per la correzione e per i suggerimenti, non è che mi potrtesti dire quali sono le bizzarrie e il metodo deprecated?
Per quanto riguarda il file a me lo salva, e non mi ricordo di aver corretto nulla, comunque ricontrollo tutto.
Ancora grazie mille.
Il metodo deprecated è Properties.save(...), sostituito con Properties.store(...) che ha la stessa segnatura ma, stando alla documentazione, "emette" un eccezione di IO nel caso in cui si verifichino problemi in scrittura (cosa che save(...) non fa, sempre documentazione alla mano).
Le bizzarrie stanno nello standard che hai adottato per il nome delle variabili, della classe e dei metodi. Esiste uno standard Java non ufficiale ma affermato secondo cui i nomi delle classe hanno l'iniziale maisucola, se sono composti di due o più parole ciascuna parola ha l'iniziale maiuscola (es. class NomeMiaClasse ...). I metodi e le variabili viceversa hanno l'iniziale sempre minuscola (es.nomeMiaVariabile, nomeMioMetodo()).
E' indifferente seguire o meno questo tipo di notazioni, di solito però il programmatore si sceglie una notazione standard (potresti trovare preferibile ad esempio usare solo caratteri minuscoli separati da un "underline" "_" o qualsiasi altro sistema tu preferisca).
Tu hai 31 variabili per le quali usi la notazione minuscola, 10 maiuscole, la superclasse è "wan", la prima classe annidata si chiama "Valori"...mi sfugge la logica delle notazioni anche se questo non vuol dire che non ci sia.
I nomi "c1... t1.... l1....", di solito dovrebbero essere "significativi", brevi ma che suggeriscano ciò che fanno.
Solo un'idea: per le operazioni sui file potresti usare uno flusso con buffer, è vero che scrivi pochi bytes, ma è più "fine" (e meglio per il sistema) ed è necessario aggiungere solo mezza riga di codice
in
BufferedInputStream inBuffer=new BufferedInputStream(new
FileInputStream(f));
...
proprieta.load(inBuffer);
inBuffer.close();
out
BufferedOutputStream outBuffer=new BufferedOutputStream(
new FileOutputStream(nomedirectory + nomefile));
proprietà.save(outBuffer);
outBuffer.flush();
outBuffer.close();
Il "flush()" assicura che il buffer svuoti il suo contenuto sul disco prima di essere chiuso.
Questo mi fa impazzire (è perfetto perchè funziona, ma è un pugno in un occhio per chi legge)
t1.setEditable(false);t2.setEditable(false);t3.setEditable(false);
t4.setEditable(false);t5.setEditable(false);t6.setEditable(false);
t7.setEditable(false);t8.setEditable(false);t9.setEditable(false);
t10.setEditable(false);
Costruisci un metodo, puoi anche chiamarlo:
impostaIlParametroEditableDelleTextBox(boolean valore) {
t1.setEditable(valore)....t10.setEditable(valore);
}
Nascondilo nelle riga più bassa del codice e poi lo usi quanto ti serve (almeno 3 volte se non sbaglio).
Se usassi un array potresti inizializzare e impostare le text box in due cicli
TextBox[] textBoxes=new TextBox[10];
for(int i=0;i<textBoxes.length;i++) {
textBoxes[i]=new TextBox();
}
.
Al solito tutto dipende dallo scopo dell'esercizio, fare un programma che funzioni (e il tuo programma è perfetto), oppure il professore è curioso di vedere lo stile del programma (il tuo è al 95% perfetto, perchè funziona e questo è sempre determinante, però quà e là ci si può ricamare sopra).
Ciao.
Grande PGI, approvo lo speghino in tutto e per tutto!
Originariamente inviato da cn73
Grande PGI, approvo lo speghino in tutto e per tutto!
Buon vecchio CN73! Sapessi che voglia ho di mollare tutto andare a studiare informatica, passerei 4 anni a sguazzare in Java! E invece me ne stò qua a fustigarmi con una tesi che già detesto.
Shadylane, esattamente lo scopo dell'esercizio che devi fare per l'esame qual'è? Vogliono verificare la conoscenza dei parametri principali per configurare una "wide area network" o vogliono un'applicazione grafica in Java che abbia come scopo generico quello sopra?
Perchè non vorrei che alla fine ti facessimo perdere del tempo su una parte (quella dell'interfaccia grafica) che non conta nulla ai fini del tuo esame...
Se l'obiettivo è il primo (conoscenza di parametri di congifurazione e, ad abundantiam, una gestione grafica) lasciala com'è e fai un salto in spiaggia.
Se vogliono un'applicazione "completa" potresti aggiungere metodi a volontà...alla fine ciò che conta è: "Il professore dà 30 facilmente o è uno un po' 'avaro' "?
Ciao.
shadylane
08-08-2003, 06:10
Lo scopo del mio progetto è di creare una interfaccia grafica per un programma di emulazione che già esiste ma che funziona da linea di comando, quindi mi dovrei concentrare su finestre e finestrelle, bottoni, etc... e rendere il tutto bello da vedere e semplice da usare. Per quanto riguarda il prof non so che metodi di giudizio adotta, quindi adottero tutte le correzioni che mi avete consigliato. :)
Caro PGI, io sono uno di quelli che crede che nella vita bisogna seguire il proprio istinto e che non sia mai troppo tardi per farlo ;) Ricorda inoltre che per fare il programmatore non serve una laurea o meglio ne puoi avere una in qualunque cosa :D
shadylane, se vuoi qualche info ufficiale sulle convenzioni del Java, dai un occhio qui: http://java.sun.com/docs/codeconv/index.html
Prima o poi prendo il toro per le corna e vado a cercarmi un javalavoro! :D
Originariamente inviato da shadylane
Lo scopo del mio progetto è di creare una interfaccia grafica per un programma di emulazione che già esiste ma che funziona da linea di comando, quindi mi dovrei concentrare su finestre e finestrelle, bottoni, etc... e rendere il tutto bello da vedere e semplice da usare.
Tre parole, passa a swing.
A dimostrazione del poco tempo che ho da perdere :D :
http://web.infinito.it/utenti/t/triboniano/sample.png
Benchè possa sembrare un pannello "mordi e fuggi" c'è dentro un po' di tutto, dai LookAndFeel Themes alle scritte html nelle etichette.
Se vuoi (e giuri che non copi :D ) ti passo il sorgente, magari ti dà qualche idea.
Ciao.
shadylane
08-08-2003, 15:07
Originariamente inviato da cn73
shadylane, se vuoi qualche info ufficiale sulle convenzioni del Java, dai un occhio qui: http://java.sun.com/docs/codeconv/index.html
Ottimo, ora vado
shadylane
08-08-2003, 15:12
Originariamente inviato da PGI
Prima o poi prendo il toro per le corna e vado a cercarmi un javalavoro! :D
Tre parole, passa a swing.
A dimostrazione del poco tempo che ho da perdere :D :
http://web.infinito.it/utenti/t/triboniano/sample.png
Benchè possa sembrare un pannello "mordi e fuggi" c'è dentro un po' di tutto, dai LookAndFeel Themes alle scritte html nelle etichette.
Se vuoi (e giuri che non copi :D ) ti passo il sorgente, magari ti dà qualche idea.
Ciao.
Mi stai tentando, all'inizio avevo anche provato con le swing, ma mi sento più a mio agio con le awt, le conosco da più tempo e poi mi sembrano a prova di imbecille :D (cioè io).
Piuttosto ho apportato delle modifiche al codice, ho inserito una funzione per visualizzare una finestra in caso di errore, ma il problema è che la grafica non viene sovrascritta, ma si mette in coda. Va be se lo provate è meglio, la funzione è finestraErrore.
Le AWT sono ormai superate, e le SWING non sono poi così complesse...
Avete dato un'occhiata all'esempio dirDiInstallazioneJava\demo\jfc\SwingSet2\SwingSet2Plugin.html?? E' molto significativo sulle loro potenzialtà...
shadylane
08-08-2003, 15:24
Originariamente inviato da cn73
Le AWT sono ormai superate, e le SWING non sono poi così complesse...
Avete dato un'occhiata all'esempio dirDiInstallazioneJava\demo\jfc\SwingSet2\SwingSet2Plugin.html?? E' molto significativo sulle loro potenzialtà...
bellissimo
:eek:
Il + bello però è senza dubbio Java2dDemo nella stessa directory ;)
Originariamente inviato da cn73
Il + bello però è senza dubbio Java2dDemo nella stessa directory ;)
E' il mio preferito, il bello è che fa macinare alla jvm un bel po' di algoritmi, a guardarlo c'è da ricredersi sulla cronica "lentezza" di java
Originariamente inviato da shadylane
la funzione è finestraErrore.
Il metodo finestraErrore ha un po' di magane: ad ogni chiamata il frame "mioDialog" si vede aggiungere altri 3 componenti, non sostituisce i precedenti.
Per sistemarlo dovresti ricreare l'oggetto mioDialog ad ogni chiamata del metodo aggiungendo
mioDialog=new Dialog(frameErrore,"Errore");
alla riga 310.
Ti consiglierei vivamente di sostituire il contenuto del metodo finestraErrore con questo:
JOptionPane.showMessageDialog(this,errore,"Errore",JOptionPane.WARNING_MESSAGE);
ricorda di importare il package javax.swing
Con l'aiuto di JBuilder ed il buon vecchio copia e incolla ho cambiato i componenti awt in componenti swing: in pratica adesso hanno una J davanti (TextField -> JTextField Checkbox -> JCheckBox ecc).
Ad eccezione del CheckboxGroup (che in swing diventa un ButtonGroup) è tutto uguale, riga per riga.
Ho aggiungo un commento per evidenziare i punti principali in cui è cambiato il codice.
Dovresti però prendere in considerazione la possibilità di separare il codice (500 e passa linee) in almento 3 classi diverse
wan (frame principale)
selezionaOpzioni (pannello)
settaValori (pannello).
L'action listener poi è obiettivamente troppo lungo. Dovresti anche qui creare 3 classi diverse, ciascuna delle quali implementi lìinterfaccia ActionListener, una poi la usi per la gestione degli eventi della barra dei menu, una per il gruppo di JCheckBox, una per l'esecuzione dei comandi.
Sempre parlando di gestione degli eventi, usare un confronto con getActionCommand() non è propriamente salutare. Il problema è che i component prendono di default la stringa dall'etichetta. Se il codice si allunga ti potrebbe capitare di usare due volte una stringa (ad esempio "ok") per due componenti, e dovresti scrivere qualche riga in più per gestire la faccenda (al limite una sola con setActionCommand(String) se disponibile).
Considera anche che il confronto tra stringhe operato negli if dell'ActionListener non è proprio il modo più efficiente che ha Java per verificare quale componente abbia generato l'evento (il confronto tra stringhe viene eseguito carattere per carattere, niente di trascendentale per un PC odierno anche con stringhe molto lunghe, ma è "brutto"). Viceversa, un confronto fatto con l'oggetto sorgente (esempio: actionEvent.getSource()==bottoneSalva) è più rapido perchè viene controllata una corrispondenza tra indirizzi di memoria.
Ciao.
shadylane
09-08-2003, 08:06
Che dirti...un miliardo di grazie.
Adesso comincio a lavorarci, intanto ti chiedo altre 2 cose: se separo il tutto in 3 classi, come le "unisco"? Devo mettere un import oppure inserirle in un package?
Una volta compilato il file in versione definitiva, come faccio ad eseguirlo senza dover ogni volta utilizzare l'opzione del jcreator?
Originariamente inviato da shadylane
Che dirti...un miliardo di grazie.
Adesso comincio a lavorarci, intanto ti chiedo altre 2 cose: se separo il tutto in 3 classi, come le "unisco"? Devo mettere un import oppure inserirle in un package?
Una volta compilato il file in versione definitiva, come faccio ad eseguirlo senza dover ogni volta utilizzare l'opzione del jcreator?
Puoi fare con o senza package. La differenza stà nel fatto che con il package puoi tenere tutte i file class in una cartella (che abbia lo stesso nome del package) e lanciare il programma dall'esterno della directory con
java nomepackage.classemain [invio]
L'uso delle classi appartenenti ad un package non richiede un import se effettui l'accesso dall'interno del package stesso: ad esempio, avendo un package di nome "wanpack" che contiene le classi wan, pannello1, frame1, dalla classe "wan" puoi costruire oggetti "pannello1" e "frame1" senza import:
package wanpack;
class wan {
Pannello1 pannello=new Pannello1();
wan() {
this.getContentPane().add(pannello);
}
}
Lo stesso risultato si ottiene anche senza package: se nella directory della classe principale (wan) sono presenti i file class degli altri oggetti (pannello1 e frame1). Questo perchè il comando
java nomeclasse
è equivalente a
java -classpath "xxx; yyy" nomeclasse
dove xxx è la directory della variabile di sistema "path" e yyy la directory corrente di esecuzione di "java".
Viene da chiedersi il motivo dell'esistenza del "package", visto che alla jvm è sufficiente che le classi siano raggruppate e la clausola import si può usare anche su una classe "singola".
Beh, il package in Java è semplicemente un utilità la cui assenza non incide sull'esecuzione del programma ma "semplifica" il raggruppamento dei modelli per gli oggetti (i file class). Si può pensare al package come alle "cartelle" in cui è suddiviso il contenuto di un hard-disk in Windows, se ne può fare benissimo a meno, ma avere tutti i file insieme rnde la situazione più "confusa".
Una volta che il tuo programma sarà completo potrai usare un file jar per la "distribuzione". Per farlo devi creare con un editor di testo (notepad va benissimo) un file di manifesto che abbia il seguente contenuto:
[da qui escluso]
Main-Class: wan
[a qui escluso]
se hai usato un package:
[---]
Main-Class: nomepackage.wan
[---]
E' importante che termini con un'interruzione di linea (invio). Salvi il file (è indifferente il nome e il formato, alcuni lo salvano come Manifest.mf, altri come Manifest.txt ecc.)
con l'utility "jar" crei l'eseguibile jar con il comando:
jar mcf nomeFileManifest.estensione Wan.jar nomeclasse1.class nomeclasse2.class [ecc.]
oppure
jar mcf nomeFileManifest.estensione Wan.jar *.class
(include nel jar Wan.jar tutti i file class che trova nella directory di esecuzione)
o ancora (con un package e un manifesto per package)
jar mcf nomeFileManifest.estensione Wan.jar directoryPackage/
il programma può essere lanciato con il comando
java -jar Wan.jar
o con un doppio click sul file Wan.jar e viene distribuito come file unico.
Ciao.
shadylane
09-08-2003, 13:26
Risolto un problema se ne crea un altro (prima o poi mi fucilerai):
prima di leggere la tua risposta ho fatto questo: ho creato 1 progetto e vi ho inserito dentro i 3 file .java con le suddivisioni che mi hai suggerito, ma se per ogni file .java non reinserisco le variabili e le funzioni che sono presenti nella classe (e quindi mi risulatano le ripetizioni delle variabili) mi da errore quando compilo. Perchè?
Detta così sembra magia nera :eek: , è possibile che tu stia cercando di accedere dalla classe wan ad una varibile presente nella classe, ad esempio, settaValori? Se così fosse, devi ricordare che con la separazione dei file sorgente ora settaValori ha perso la qualifica di "nested class" (classe annidata) e dispone di un'area di visibilità separata da quella di wan. Per l'accesso, ad esempio, al campo di testo "t1" di "settaValori" devi usare l'operatore punto su un oggetto "settaValori". Ai tuoi fini ricordo anche che deve esistere un solo oggetto "settaValori" creato nella classe wan con l'operatore new, possibilimente in un'area in cui sia dotato di visibilità di classe in modo da poter accedere ai suoi elementi anche dalle classi annidate di wan che rappresentano i gestori di evento.
Se ti sembra che il problema non sia questo direi che,se possibile, avrei bisogno di dare un'occhiata al nuovo codice sorgente.
Ciao.
shadylane
09-08-2003, 19:22
Credo che il problema sia quello che mi hai detto del punto, risolverò al più presto.
shadylane
10-08-2003, 08:15
:( proprio non capisco dove sto sbagliando, continua a darmi degli errori qualsiasi modifica io faccia, l'unico codice prseudofunzionante è quello che ti allego
Originariamente inviato da shadylane
:( proprio non capisco dove sto sbagliando, continua a darmi degli errori qualsiasi modifica io faccia, l'unico codice prseudofunzionante è quello che ti allego
Dovresti distribuire i compiti tra le classi prima di scrivere il codice.
Diciamo che "settaValori" fa da contenitore per i campi di testo e le relative etichette: i checkbox non sono pane per i suoi
denti. Eliminiamoli (righe da 22 a 32). IL costruttore di "settaValori" richiede come parametro un "Frame". Il parametro però
non è mai usato. A meno che tu non abbia intenzione di attribuirgli un qualche funzione toglierei anche quello:
public "settaValori(Frame frame2)" diventa "public settaValori()"
Anche la variabile Frame "frame2" (riga 21) è dichiarata e mai usata...facciamole fare una brutta fine (cancellata)
Facciamo un salto nel buio: "settaValori" ha bisogno di un altro metodo (vedremo dopo perchè):
lo chiamiamo "resettaCampi" e il suo contenuto è praticamente identico ad alcune righe di codice che hai usato in "wan"
/**
*Imposta il valore dei campi di testo ad una stringa vuota
*/
public void resettaCampi() {
t1.setText("");t2.setText("");t3.setText("");t4.setText("");t5.setText("");
t6.setText("");t7.setText("");t8.setText("");t9.setText("");t10.setText("");
}
Fatto. Via con la prossima.
"selezionaOpzioni":
Qui hai deciso di mettere le caselle di selezione: textfields e labels perdono significato, le righe da 34 a 55 svaniscono.
Se ne va anche il metodo "settaTextFieldEditable(boolean)": lasciamo che sia la classe "settaValori" "proprietaria" dei campi
di testo, a gestire questa operazione sui TextField.
L'argomento "Frame frame1" del costruttore di "selezionaOpzioni" può essere eliminato: vale quanto detto per "settaValori".
Cominciano i problemi: "selezionaOpzioni" ha tra i suoi scopi quello di controllare lo stato dei campi di testo, che però si
trovano in "settaValori". E' un tipico problema di riferimenti.
Si nota subito che il "punto di incontro" delle due classi "selezionaOpzioni" e "settaValori" è la classe "wan". Inoltre
"selezionaOpzioni" si riferisce ai campi di testo di "settaValori" all'interno del metodo di un gestore di eventi.
La via più semplice sembra pertanto quella di passare attraverso un gestore di eventi che risieda in "wan".
Ecco come:
al costruttore di "selezionaOpzioni" facciamo "chiedere" come argomento un'interfaccia "ItemListener":
public selezionaOpzioni(ItemListener itemListener) {...
Ora usiamo l'argomento come gestore di eventi per le checkbox:
c1.addItemListener(itemListener);c2.addItemListener(itemListener); ecc...
Da "selezionaOpzioni" rimuoviamo l'implementazione dell'interfaccia (implements ItemListener e il relativo metodo
itemStateChanged) perchè siamo passati ad un altro gestore di eventi, che abbiamo intenzione di "infilare" nella classe Wan.
Passiamo pertanto a "wan".
Hai già dichiarato due variabili per gli oggetti "selezionaOpzioni" e "settaValori". Ben fatto, adesso vediamo di mettere
insieme tutto.
Creiamo subito una classe annidata per l'interfaccia "ItemListener", così ci leviamo il pensiero. IL contenuto del metodo
itemStateChanged è uguale a quello che si trovava in selezionaOpzioni. Scriviamo alla riga 403 (cioè prima che si chiuda la
classe "wan"):
/**
*ItemHandler gestisce gli eventi associati alle caselle di selezione
*/
class ItemHandler implements ItemListener {
public void itemStateChanged (ItemEvent e) {
//controllo se i checkbox 5 o 7 sono stati selezionati: se si abilito
//i text field, altrimenti disabilito
if((mioSelezionaOpzioni.c5.getState())||(mioSelezionaOpzioni.c7.getState())) mioSettaValori.settaTextFieldEditabile(true);
else mioSettaValori.settaTextFieldEditabile(false);
}
}
Nota l'operatore punto per l'accesso ad elementi della classe settaValori e selezionaOpzioni.
Ora che abbiamo chi si occupa della gestione delle caselle di testo, dobbiamo passare come argomento del costruttore di
"selezionaOpzioni" un'oggetto creato sul modello di "ItemHandler":
riga 180:
mioSelezionaOpzioni=new selezionaOpzioni(new ItemHandler());
Già che ci siamo cambiamo anche la riga 181 (ricordo che il costruttore di settaValori è cambiato, ora non ha più argomenti):
mioSettaValori = new settaValori();
Compilando i tre sorgenti ed eseguendo si scopre che ora le caselle di testo fanno quello che ci si aspetta da loro ;).
Adesso dovremmo passare l'aspirapolvere nella classe "wan" perchè contiene qualche riga di codice che non ha più senso con la separazione, ma prima ti lascio "digerire" il panegirico che ho scritto.
shadylane
11-08-2003, 20:43
Rieccomi qua :D
ho digerito il panegirico, anzi ho fatto anche di più, ho apportato qualche modifica: ho creato una classe per il menù, in modo da dividere l'actionPerformed, e vorrei fare la stessa cosa per il pannello col bottone esegui e reset e per la finestra degli errori (che per ora è solo una funzione) in modo tale da eliminare l'actionPerformed dalla classe wan. Mi sorge un dubbio ed ho un errore: è giusto procedere come ho fatto io, e cioè creando piccole classi ognuna col proprio actionPerformed, oppure mi incasino e/o rendo il tutto illeggibile e/o è una cosa che non si fa e basta?
L'errore riguarda il file dialog per il salvataggio e la lettura mi dice che non trova la variabile, ho provato a metterla dappertutto, ma continua a darmi l'errore, why??
Da me il programma "gira" senza apparenti errori (salva e legge correttamente le impostazioni).
E qui finiscono le buone notizie. Eravamo su migliori strade con la versione precedente: tre classi in tre sorgenti.
Adesso abbiamo una classe (wan) e all'interno due classi annidate (selezionaOpzioni e settaValori). Non è piacevole da leggere (e il sorgente che non è piacevole da leggere rende spiacevole la fase di debug e successive revisioni. Non credo che ora tu sia interessato a questi momenti della produzione di software, ma se possibile è meglio partire col piede destro :) )
Considera la tua applicazione da questo punto di vista: hai una finestra principale che contiene un pannello per le caselle di selezione, un pannello per i campi di testo, un pannello per l'esecuzione di comandi (e aggiungerei anche la barra dei menu).
E' una cosa naturale pensare a questi elementi come a tre (4) oggetti distinti. Oggetti distinti -> classi diverse -> codice separato.
Ti assicuro che con i codici separati ti troverai a poter cambiare la veste grafica del tuo programma con una facilità di gran lunga maggiore rispetto al sorgente che hai adesso.
Segui il consiglio di questo caprone che stà scrivendo: lascia inalterato il codice che hai allegato (extrema ratio, da consegnare in caso di morbo del disco fisso, rottura della cpu, fulmini o cavallette) e parti con un altro progetto. Poi chiudi JCreator e apri Paint (o un equivalente) e disegna l'interfaccia grafica che vuoi creare (non è uno scherzo, il punto di partenza del settore grafico di un team di sviluppo per software a volte è un disegno sul tovagliolo di un ristorante).
Benchè possa sembrare "avventato", quello che avrai disegnato sarà quello che potrai ottenere (swing è tra le più avanzate librerie per interfacce grafiche sul mercato).
Limiti? Due: la finestra dev'essere rettangolare (esiste un workaround ma non è a prova di roccia) e la barra del titolo è blandamente personalizzabile (a meno di riscrivere un LookAndFeel). E' un errore comune pensare che sia impresa che richieda chissa quali abilità: add,set e pensare per oggetti. Se aggiungi anche un buon "pensa semplice" puoi mandare in pensione un buon numero di programmatori.
Non posso scriverti il codice e mi sembra che tu nemmeno lo voglia. Ma se posti l'immagine dell'interfaccia che vorresti posso darti un'idea degli oggetti che devi usare e su come dividere il codice sorgente.
Ciao.
shadylane
12-08-2003, 08:01
scusa ma ho allegato lo zip sbagliato :muro: :muro: :muro: :muro:
Allora ho pontificato a vanvera :D
Il problema in compilazione è dovuto al fatto che FileDialog richiede un argomento Frame per il costruttore. "this" è una parola chiave che si riferisce all'oggetto che "chiama" il metodo in cui è contenuta. Nel tuo caso "this" sta per "un'istanza di barraMenu". La faccenda si può risolvere in vari modi. Puoi creare due oggetti FileDialog nella classe wan (con visibilità di classe per le variabili relative), un "saveDialog" e un "loadDialog" che inizializzi nel costruttore di "wan" (e lì puoi usare this con i risultati voluti). Nell'actionPerformed di "barraMenu" richiami i metodi "saveDialog.setVisible(true)" e "loadDialog.setVisible(true)", evitando oltretutto un'inizializzazione ripetuta.
Nel blocco if alla riga 382 del sorgente di wan puoi usare il metodo mioSettaValori.resettaCampi() anzichè impostare i singoli campi di testo.
Puoi anche considerare l'opzione di usare una array di TextField al posto di dichiarare 10 campi di testo con nome generico (cambia la forma ma non la sostanza).
Una nota di "colore": in commento di questo tipo
/************************
...
************************/
non è propriamente corretto (se l'hai visto in un pezzo di codice che ho mandato io allora vuol dire che ho fatto una sciocchezza). Nel jdk esiste uno strumento, javadoc, usato per generare la documentazione di classi o package. I commenti "standard" sono
"/*...*/" e "//". Una barra destra seguita da due asterischi è invece un commento "javadoc" ("/**") che ha una funzione ed una sintassi autonoma. Non che sia un problema di vita o di morte, è solo "per saperlo" :)
Noto (wan, linea 270) che hai scelto la via breve per correggere il bug della finestra di dialogo di errore (reinizializzazione dell'oggetto dialog ad ogni chiamata). Anche qui non è un errore ma è al tempo stesso non è un esempio di efficienza.
Puoi creare una classe separata per la finestra di dialogo, "regalarle" un metodo "showErrorMessage(String msg)" e poi creare un'oggetto su quel modello nel costruttore di wan. A questo punto nel metodo wan.finestraErrore(String) non faresti altro che richiamare quel metodo "showErrorMessage(String)".
Di solito inoltre le finestre di dialogo compaiono al centro del frame a cui appartengono, dovresti rivedere la locazione (prendi le dimensioni del frame "wan", dividi per due altezza e larghezza, sottrai la metà dell'altezza e della larghezza del dialog alla metà dell'altezza e larghezza del frame e dovresti ottenere la locazione corretta).
Per chiarimenti...son sempre qui.
Ciao.
shadylane
12-08-2003, 16:13
Ho fatto altre correzioni, e direi che mi sembre di aver finito;
ho creato una classe esterna finestraErrore che implementa l'actionListener, ed una classe main che contiene le poche righe del main (spero che quest'ultima modifica sia accettabile, non mi piaceva dedere una classe con in mezzo il main, ne interrompeva la continuità :D :eek: :cool: )
Ultima cosa: come mi hai detto in precedenza, se importo le swing, se metto la j davanti a tutte le variabili, se cambio il checkboxgroup con buttongroup, è ancora tutto uguale riga per riga, come mi avevi detto?
Originariamente inviato da shadylane
...una classe main che contiene le poche righe del main (spero che quest'ultima modifica sia accettabile, non mi piaceva dedere una classe con in mezzo il main, ne interrompeva la continuità :D :eek: :cool: )
Intuizione particolarmente felice. E caldamente consigliabile infatti separare il metodo main in una classe "tutta sua" per ragioni di evidenza nella struttura del gruppo di classi. Complimenti! :D
Originariamente inviato da shadylane
Ultima cosa: come mi hai detto in precedenza, se importo le swing, se metto la j davanti a tutte le variabili, se cambio il checkboxgroup con buttongroup, è ancora tutto uguale riga per riga, come mi avevi detto?
Aggiungengo che una JMenuBar si imposta con jframe.setJMenuBar(...) e un JFrame esige che si passi per il suo pannello del contenuto per "attaccargli" degli elementi ( JFrame.getContentPane().add(Component) ) la risposta è sì.
Siccome hai già un'interfaccia funzionante ti suggerirei però di provare a rifarne una da zero ora che hai una dimestichezza maggiore con classi separate e l'interazione incrociata (ricorda il mitico metodo del finestra disegnata con paint e riprodotta nel sorgente).
Una cosa soltanto, è normale che premendo il pulsante esegui venga sempre mostrato il pannello di errore? Dal codice non mi sembra che vi sia un controllo sul contenuto delle caselle di testo, è un'anomalia o deve fare così?
Ciao.
shadylane
12-08-2003, 16:49
Originariamente inviato da PGI
Intuizione particolarmente felice. E caldamente consigliabile infatti separare il metodo main in una classe "tutta sua" per ragioni di evidenza nella struttura del gruppo di classi. Complimenti! :D
grazie :)
Una cosa soltanto, è normale che premendo il pulsante esegui venga sempre mostrato il pannello di errore? Dal codice non mi sembra che vi sia un controllo sul contenuto delle caselle di testo, è un'anomalia o deve fare così?
Ciao.
Sì è normale, perchè non trova il file eseguibile interf (che ha l'assistente del prof, e che mi dovrò far mandare, altrimenti scoprirò se funziona solo al momento dell'esame).
Grazie mille per tutti gli aiuti e per la pazienza, ti devo una cena
http://tubes.ominix.com/art/a/food/beef-steak-dinner-plate.png
shadylane
24-09-2003, 20:41
Esame passato con un bel 30
Grazie mille a tutti:D
Beh, un 30 si commenta da solo, bravo&complimenti :)
Ciao (secchione :D).
shadylane
25-09-2003, 17:36
Be' una parte la dedico a voi che mi avete aiutato.
:)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.