PDA

View Full Version : Come si fa ?


spillo491
01-04-2007, 11:58
Ciao a tutti devo realizzare un programma ma non so da che parte incominciare:

devo costruire una griglia con assi numerati e dare la possibilità all'utente di indicare dei punti su di essa. In particolare:
1 click --> pallino su griglia
2 click --> croce su griglia
In base alle regioni della griglia in cui si hanno pallini e croci il programma deve elaborare i dati e dare un uscita secondo una funzione conosciuta

Mi sapete dare qualche idea ?

Io so programmare un po in java e so usare Matlab

spillo491
13-04-2007, 13:43
Nessuno mi sa dare un'idea su come procedere ?

PGI-Bis
13-04-2007, 14:40
E' difficile darti un'idea senza offrire anche la soluzione completa dell'esercizio.

Potresti iniziare creando un oggetto Griglia che conservi una matrice di oggetti Simbolo (PALLINO o CROCE).

Dai alla griglia la capacità di modificare il valore di una delle sue celle.

Crea un ascoltatore di eventi prodotti dalla griglia.

Quando la griglia subisce la modifica di una delle sue celle, dopo aver immagazzinato la modifica, le fai sparare un evento in direzione di tutti gli ascoltatori registrati.

Crea un pannello che proietti sullo schermo i dati della griglia. Dota questo pannello di un ascoltatore di eventi che sia connesso alla griglia.

Quando questo ascoltatore riceverà un evento dalla griglia, proietterà sullo schermo le modifiche intervenute (un pallino o una crocetta nella posizione stabilita per la cella modificata).

Quando giunge il momento di calcolare la funzione, prendi la griglia e la passi ad un oggetto, chiamiamolo Processore, che analizza i valori delle celle e, in base ad una logica da te stabilita, produca la Funzione.

E' più facile a farsi che a dirsi.

spillo491
13-04-2007, 14:47
Grazie mille PGI, a me non sembra poi cosi facile :doh: perchè sono alle basi della programmazione però ci provo.
Quindi posso fare tutto in java ?

PGI-Bis
13-04-2007, 14:53
Yesssss. Tu prova. Se incontri difficoltà chiedi.

spillo491
16-04-2007, 11:35
Ma in pratica devo realizzare un APPLET ? :rolleyes:

andbin
16-04-2007, 11:48
Ma in pratica devo realizzare un APPLET ? :rolleyes:Se deve stare dentro una pagina HTML, sì. Altrimenti crei una normale applicazione. Puoi stabilirlo tu, se non ti sono state date precise specifiche.

PGI-Bis
16-04-2007, 11:53
Non lo so ma sospetto di no.

Un Applet Java è un programma eseguito all'interno di un web browser distribuito attraverso una pagina html.

Eventualmente è dotato di un'interfaccia grafica utente che può apparire come una finestra o come un elemento dinamico della pagina html.

Io penso che tu voglia o deva realizzare un programma stand-alone: autonomo, dove l'autonomia vale "non serve il web browser".

Dunque, niente Applet.

lovaz
16-04-2007, 11:55
Ci sarebbe appletviewer.

PGI-Bis
16-04-2007, 12:07
appletviewer è uno strumento di sviluppo incluso nel JDK che non appartiene alla piattaforma Java standard.

spillo491
16-04-2007, 12:10
Si avete ragione, io non voglio un programma che sia eseguito da un web browser ma un programma stand alone.
Quindi questo codice che avevo trovato in rete non posso riutilizzarlo ? :eek:

import java.awt.*;

public class DrawAndClick extends java.applet.Applet {

//

public boolean mouseDown(Event e, int x, int y) {

// il metodo getGraphics() della classe BufferedImage
// restituisce un oggetto Graphics
Graphics g = getGraphics();
g.fillRect(x-2,y-2,4,4);

return true;
}

public void paint(Graphics g) {

int i, j;

// Disegno una griglia con assi che vanno da 0 a 300
// Ogni quadratino ha lato 30

for(i=0; i<=300; i=i+30) {
// disegna le linee verticali della griglia
//public void drawLine(int x1, int y1, int x2, int y2)
g.drawLine(0,i,300,i);
// disegna le linee orizzontali della griglia
g.drawLine(i,0,i,300);
}
}

}

lovaz
16-04-2007, 12:17
appletviewer è uno strumento di sviluppo incluso nel JDK che non appartiene alla piattaforma Java standard.
Non sapevo...

Comunque puoi facilmente convertire quell'applet in applicazione,
vedi ad esempio qui:
http://www.rgagnon.com/javadetails/java-0305.html
Aggiungi una J davanti a Panel, Frame, Button...

PGI-Bis
16-04-2007, 12:28
Occhio che quel codice non solo e non tanto è vecchio (Java 1.1) ma fa un uso non corretto della pipeline di rendering di Java.

Se mi dai 5 minuti butto giù un esempio di griglia. So che, essendo un esercizio scolastico, potrebbe sembrare non corretto ma se non v'hanno spiegato nulla di interfacce grafiche utente, disegno e Swing tanto vale prendere l'esercizio come primo passo in quest'universo. Comunque scrivo solo una traccia, un indizio.

spillo491
16-04-2007, 12:32
Ok grazie

lovaz
16-04-2007, 12:46
Effettivamente fa un po' schifo...
colpa della mia pigrizia, ho messo il primo link di google :muro: :D

spillo491
16-04-2007, 12:49
Ma credo si riferisca al mio codice :confused:

PGI-Bis
16-04-2007, 14:11
M'è venuto non breve ma piuttosto esplicito.

Con pallini e crocette.

/** Rappresentazione di un tipo di dato "Simbolico" */
public enum Simbolo {
VUOTO,
PALLINO,
CROCE
}

mettiamo su una griglia:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/** Rappresentazione di una griglia di simboli. */
public class Grid {
/* Numero di righe della griglia */
private final int numeroDiRighe;

/* Numero di colonne della griglia */
private final int numeroDiColonne;

/* Contenuto della griglia */
private final Simbolo[] celle;

/** Inizializza una griglia */
public Grid(int numeroDiRighe, int numeroDiColonne) {
this.numeroDiRighe = numeroDiRighe;
this.numeroDiColonne = numeroDiColonne;
celle = new Simbolo[numeroDiRighe * numeroDiColonne];
inizializzaCelle();
}

/** Restituisce il numero di colonne che compongono questa griglia */
public int getNumeroDiColonne() {
return numeroDiColonne;
}

/** Restituisce il numero di righe che compongono questa griglia */
public int getNumeroDiRighe() {
return numeroDiRighe;
}

/** Restituisce il simbolo contenuto in una cella della griglia */
public Simbolo getSimboloCella(int indiceRiga, int indiceColonna) {
return celle[subscript(indiceRiga, indiceColonna)];
}

/** Imposta il simbolo contenuto in una cella della griglia */
public void setSimboloCella(Simbolo simbolo, int indiceRiga, int indiceColonna) {
celle[subscript(indiceRiga, indiceColonna)] = simbolo;
}

/** Restituisce il numero di celle della griglia */
public int getNumeroDiCelle() {
return celle.length;
}

/** Restituisce la cella di indice subscript */
public Simbolo getSimboloCella(int indiceSubscript) {
return celle[indiceSubscript];
}

/* Calcola l'indice di accesso agli elementi di una matrice linearizzata */
public int subscript(int indiceRiga, int indiceColonna) {
return indiceRiga * numeroDiColonne + indiceColonna;
}

/* inverso di subscript */
public void superScript(int indiceCella, java.awt.Point result) {
result.x = indiceCella % numeroDiColonne;
result.y = indiceCella / numeroDiColonne;
}

/* Crea una matrice linearizzata e assegna ad ogni elemento un
valore iniziale */
private void inizializzaCelle() {
java.util.Arrays.fill(celle, Simbolo.VUOTO);
}
}

Questa è una mezza vista. Ti risparmio l'architettura MVC anche se la griglia sarebbe un ottimo esempio di modello. DrawAndClick è un componente Swing (un componente è un pezzo di interfaccia grafica utente che si inserisce in un contenitore che va dentro ad una finestra) a cui è affidata, in cotruzione, una griglia (Grid) e che si occupa sia di disegnarla che di modificarla in seguito alla pressione di un pulsante del mouse.

import javax.swing.*;
import java.awt.*;
import java.awt.geom.*; //contiene le definizioni delle figure geometriche vettoriali Java2D
import java.awt.event.*;
import java.awt.image.*;

/** Vista (e controllo) su una griglia */
public class DrawAndClick extends JComponent {
/* Un buffer fuori schermo per pre-calcolare il disegno della
griglia. Assume un valore in initializeBackBuffer(), dopo addNotify(). */
private BufferedImage backBuffer;

/* La pipeline di rendering del buffer fuori schermo. Assume un
valore in initializeBackBuffer(), dopo addNotify(). */
private Graphics2D backBufferGraphics;

/* Rappresentazione vettoriale del "pallino" */
private Shape figuraPallino;

/* Rappresentazione vettoriale della "croce" */
private Shape figuraCroce;

/* Distanza tra il bordo della cella e le figure dei simboli */
private int margineInterno = 4;

/* Altezza di una cella */
private int larghezzaCella = 10;

/* Larghezza di una cella */
private int altezzaCella = 10;

/* Griglia di celle */
private Grid griglia;

/** Inizializza un DrawAndClick che da una veste grafica alla griglia in
argomento. */
public DrawAndClick(Grid griglia) {
this.griglia = griglia;
setDimensioniCella(larghezzaCella, altezzaCella);

/* Queste linee connettono a questo JComponent (DrawAndClick extends JComponent...)
un ascoltatore di eventi prodotti dal mouse. Il meccanismo di gestione degli eventi
di AWT/Swing farà in modo che quando l'utente prema uno dei pulsanti del mouse
nell'area del desktop occupata da questo JComponent sia invocato il metodo "mouseClicked"
del MouseListener qui associato */
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
gestisciClickDelMouse(e.getPoint());
}
});
}

/** Invocato autonomamente quando la radice dell'albero di proiezione
a cui questo componente appartiene diviene visualizzabile. A noi interessa
perchè a partire da quel momento getGraphicsConfiguration(), usato per
inizializzare il buffer backBuffer, restituisce un valore diverso da null */
public void addNotify() {
super.addNotify();
initializeBackBuffer();
}

/** Invocato in costruzione */
public void setDimensioniCella(int larghezza, int altezza) {
/* GeneralPath è un percorso vettoriale */
GeneralPath croce = new GeneralPath();
croce.moveTo(0, 0);
croce.lineTo(larghezza - margineInterno, altezza - margineInterno);
croce.moveTo(larghezza - margineInterno, 0);
croce.lineTo(0, altezza - margineInterno);
figuraCroce = croce;

/* Un ellisse per il pallino */
Ellipse2D.Float pallino = new Ellipse2D.Float(
0, 0, larghezza - margineInterno, altezza - margineInterno);
figuraPallino = pallino;

larghezzaCella = larghezza;
altezzaCella = altezza;

/* Attribuisce a questo componente Swing una dimensione di cui un
LayoutManager può tenere conto */
Dimension dimensioniPannello = new Dimension(
larghezzaCella * griglia.getNumeroDiColonne() + 1,
altezzaCella * griglia.getNumeroDiRighe() + 1);
setMinimumSize(dimensioniPannello);
setMaximumSize(dimensioniPannello);
setPreferredSize(dimensioniPannello);
}

/** Ridefinisce l'omonimo metodo di JComponent che disegna questo
componente Swing */
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
graphics.drawImage(backBuffer, 0, 0, null);
}

/* Questo metodo è invocato autonomamente quando si clicca il
mouse su questo componente. */
private void gestisciClickDelMouse(Point puntoDiPressione) {
/* Dal punto sullo schermo passa alla cella */
int indiceRiga = puntoDiPressione.y / altezzaCella;
int indiceColonna = puntoDiPressione.x / larghezzaCella;
if(indiceRiga < griglia.getNumeroDiRighe() && indiceColonna < griglia.getNumeroDiColonne()) {
cambiaSimboloCella(indiceRiga, indiceColonna);
}
}

/** Cambia il simbolo della cella di indice numeroDiRiga, numeroDiColonna */
private void cambiaSimboloCella(int indiceRiga, int indiceColonna) {
Simbolo simboloAttuale = griglia.getSimboloCella(indiceRiga, indiceColonna);
Simbolo nuovoSimbolo;
if(simboloAttuale == Simbolo.VUOTO) {
nuovoSimbolo = Simbolo.PALLINO;
} else if(simboloAttuale == Simbolo.PALLINO) {
nuovoSimbolo = Simbolo.CROCE;
} else if(simboloAttuale == Simbolo.CROCE) {
nuovoSimbolo = Simbolo.VUOTO;
} else {
throw new RuntimeException("Hai dimenticato qualcosa? :D");
}
griglia.setSimboloCella(nuovoSimbolo, indiceRiga, indiceColonna);
aggiornaProiezioneCella(indiceRiga, indiceColonna, backBufferGraphics);
repaint();
}

/* Disegna lo sfondo del contenitore */
private void disegnaSfondo(Graphics2D pipeline) {
pipeline.setPaint(Color.WHITE);
pipeline.fillRect(0, 0, backBuffer.getWidth(), backBuffer.getHeight());
}

/* Disegna l'intera griglia */
private void disegnaGriglia(Graphics2D pipeline) {
Point coordinateCella = new Point();
pipeline.setPaint(Color.BLACK);
for(int indiceCella = 0; indiceCella < griglia.getNumeroDiCelle(); indiceCella++) {
/* Tramite la griglia, ottiene la posizione (indiceDiRiga, indiceDiColonna)
della cella di indice indiceCella nella matrice della griglia. Questa posizione
è immagazzinata nel punto coordinateCella */
griglia.superScript(indiceCella, coordinateCella);

/* Disegna un rettangolo che rappresenta il bordo della cella */
int posizioneXCella = coordinateCella.x * larghezzaCella;
int posizioneYCella = coordinateCella.y * altezzaCella;
pipeline.drawRect(posizioneXCella, posizioneYCella, larghezzaCella, altezzaCella);

/* Disegna il simbolo contenuto nella cella*/
int spostamentoXFigura = posizioneXCella + margineInterno / 2;
int spostamentoYFigura = posizioneYCella + margineInterno / 2;
Simbolo simboloCella = griglia.getSimboloCella(indiceCella);
pipeline.translate(spostamentoXFigura, spostamentoYFigura);
if(simboloCella == Simbolo.PALLINO) {
pipeline.fill(figuraPallino);
} else if(simboloCella == Simbolo.CROCE) {
pipeline.draw(figuraCroce);
}
pipeline.translate(-spostamentoXFigura, -spostamentoYFigura);
}
}

/* Aggiorna una cella della griglia */
private void aggiornaProiezioneCella(int indiceRiga, int indiceColonna, Graphics2D pipeline) {
int posizioneXCella = indiceColonna * larghezzaCella;
int posizioneYCella = indiceRiga * altezzaCella;
pipeline.setPaint(getBackground());
pipeline.fillRect(posizioneXCella, posizioneYCella, larghezzaCella, altezzaCella);
pipeline.setPaint(Color.BLACK);
pipeline.drawRect(posizioneXCella, posizioneYCella, larghezzaCella, altezzaCella);
Simbolo simboloCella = griglia.getSimboloCella(indiceRiga, indiceColonna);
int spostamentoXFigura = posizioneXCella + margineInterno / 2;
int spostamentoYFigura = posizioneYCella + margineInterno / 2;
pipeline.translate(spostamentoXFigura, spostamentoYFigura);
if(simboloCella == Simbolo.PALLINO) {
pipeline.fill(figuraPallino);
} else if(simboloCella == Simbolo.CROCE) {
pipeline.draw(figuraCroce);
}
pipeline.translate(-spostamentoXFigura, -spostamentoYFigura);
}

/* Inizializza il buffer su cui è disegnata la rappresentazione della griglia */
private void initializeBackBuffer() {
backBuffer = getGraphicsConfiguration().createCompatibleImage(
griglia.getNumeroDiRighe() * altezzaCella + 1,
griglia.getNumeroDiColonne() * larghezzaCella + 1,
Transparency.OPAQUE);
backBufferGraphics = backBuffer.createGraphics();
backBufferGraphics.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
disegnaSfondo(backBufferGraphics);
disegnaGriglia(backBufferGraphics);
}
}

Resta il punto d'entrata dell'applicazione autonoma. Avrai sicuramente già visto una classe "Main", questa è una classe Main il cui metodo main apre sullo schermo una finestra. Questa finestra contiene un DrawAndClick a cui è affidato un Grid.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/** Classe principale dell'applicazione autonoma */
public class Main {

/** Punto d'entrata del programma */
public static void main(String[] args) {
/* Avvio dell'interfaccia grafica: */
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Main().apriFinestra();
}
});
}

private WindowListener ascoltatoreEventiFinestra = new WindowAdapter() {
/** Questo metodo è invocato autonomamente quando l'utente cerca di
chiudere la finestra */
public void windowClosing(WindowEvent e) {
chiudiProgramma();
}
};

/* La griglia */
private Grid griglia = new Grid(30, 30);

/* Il pannello che proietta la griglia */
private DrawAndClick contenitoreGriglia = new DrawAndClick(griglia);

/* La finestra principale del programma */
private JFrame finestra = new JFrame("DrawAndClick");

/* Inizializza i componenti dell'interfaccia */
private Main() {
/* Assegna un colore di sfondo al contenitore della griglia */
contenitoreGriglia.setBackground(Color.WHITE);
contenitoreGriglia.setOpaque(true);

/* Da una dimensione alle cella del contenitore della griglia */
contenitoreGriglia.setDimensioniCella(20, 20);

/* Collega l'ascoltatore di eventi prodotti da una finestra alla
finestra */
finestra.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
finestra.addWindowListener(ascoltatoreEventiFinestra);

/* Inserisce il pannello che proietta la griglia nella finestra */
finestra.add(contenitoreGriglia, BorderLayout.CENTER);
}

/* Proietta la finestra principale sul desktop */
private void apriFinestra() {
finestra.pack();
finestra.setVisible(true);
}

/* Da ascoltatoreFinestra.windowClosing */
private void chiudiProgramma() {
finestra.dispose();
}
}

Nota che il contenuto del metodo main, quello strano SwingUtilities.eccetera, è necessario, in quella forma o in forme equivalenti, per questioni di programmazione concorrente.

Per domande, dubbi, curiosità siamo qui.

spillo491
16-04-2007, 19:35
Sei trooppo gentile :sofico:

Ho provato a compilare e funziona !!!
Adesso me lo guardo con calma e cerco di capire il tutto

Grazie ancora

PS: Ma tu sei il pgi del forum MokaByte ?

spillo491
17-04-2007, 16:08
public void setDimensioniCella(int larghezza, int altezza) {
/* GeneralPath è un percorso vettoriale */
GeneralPath croce = new GeneralPath();
croce.moveTo(0, 0);
croce.lineTo(larghezza - margineInterno, altezza - margineInterno);
croce.moveTo(larghezza - margineInterno, 0);
croce.lineTo(0, altezza - margineInterno);
figuraCroce = croce;



L'istruzione "croce.moveTo(0, 0);" porta il cursore nell'angolo in alto a sx della cella ? Da quanto ho capito queste istruzioni dovrebbero disegnare la croce ma non mi tornano le coordinate?

PGI-Bis
17-04-2007, 16:29
No, se intendo correttamente.

GeneralPath è la definizione di un poligono da settimana enigmistica: unisci tutti i puntini e vedi cosa salta fuori.

E' uno java.awt.geom.Shape, cioè una figura geometrica 2D. Un oggetto Shape può essere rifilato al metodo draw o fill di un Graphics2D e il risultato è che la figura geometrica viene riprodotta alla foce della pipeline di rendering. Sullo schermo o in memoria, dipende. Comunque sia, la creazione di un oggetto di tipo Shape (GeneralPath ad esempio) non comporta anche il disegno di quella figura.

Le linee di codice che quoti creano e mettono da parte, per un uso futuro, una crocetta. La crocetta è fatta di due linee separate e incrociate. Le diagonali di un quadrato.

Ci sono diversi tipi di Shape nel package java.awt.geom. Non c'è la crocetta. Per crearla, quindi, uso GeneralPath. La linea:

croce.moveTo(0, 0);

usa il metodo moveTo per dire al GeneralPath: "qui inizia un segmento separato da tutti gli altri".

La linea:

croce.lineTo(larghezza - margineInterno, altezza - margineInterno);

usa il metodo lineTo per dire al GeneralPath: "immagazzina un segmento retto che parte dal punto precedente, quello del moveTo nel nostro caso, e arriva fino a (larghezza - margineIntero, altezza - margineInterno)". Una delle due diagonali di un rettangolo, quella che inizia dall'estremo in alto a sinistra e finisce in basso a destra.

La linea seguente:

croce.moveTo(larghezza - margineInterno, 0);

dice al GeneralPath di immagazzinare quel punto come l'inizio di un segmento non connesso. E' il primo punto della seconda diagonale: in alto a destra.

L'ultima linea:

croce.lineTo(0, altezza - margineInterno);

dice al GeneralPath di immagazzinare una linea che va dal punto precedente, quello del moveTo, al punto (0, altezza - margineInterno). E' il secondo punto della seconda diagonale: in basso a sinistra.

Nel sistema di coordinate della pipeline di rendering Java2D (accessibile tramite un oggetto Graphics2D), l'origine degli assi è "in alto a sinistra". X cresce "verso destra", Y cresce "verso il basso".

Ripeto, quello istruzioni creano una croce ma non la disegnano. Il disegno della croce avviene quando trovi un "pipeline.draw(figuraCroce)". Noterai come quelle istruzioni siano precedute da un "pipeline.translate". Questo perchè, come si nota nella costruzione del GeneralPath, la crocetta è costruita come una linea che parte dal punto (0,0) e va fino al punto, in ipotesi, (10, 10) più una linea che parte dal punto (10, 0) e va fino al punto (0, 10). Un semplice pipeline.draw(figuraCroce) disegnerebbe questa croce come risulta dai suoi punti: sempre in alto a sinistra dello schermo. Spostando il sistema di coordinate con translate, prima del disegno, siamo in grado di far apparire una stessa figura in punti diversi dello schermo senza cambiare le coordinate dei suoi punti (ma cambiando l'origine degli assi del sistema di coordinate a cui appartiene al figura).

spillo491
17-04-2007, 18:56
Mi sono guardato tutto il codice e ho iniziato un po a "digerirlo", poi me lo riguardo con calma.
Inserire le scale sugli assi è complicato?

PS: io ho fatto la paurosa modifica del pallino blu e la crocetta rossa :ave: :D

PGI-Bis
17-04-2007, 19:38
Be', semplice o complicato sono termini relativi.

Richiede pochi passaggi. Per la verità ne richiede tre.

1. Creare un bordo (Border) che disegna gli assi
2. Creare un JPanel in cui inserire un DrawAndClick
3. invocare setBorder su quel JPanel

E hai i tuoi assi senza toccare una virgola del resto.

spillo491
18-04-2007, 16:17
Purtroppo mio padre che mi aveva "commissionato" il lavoro si è accorto che il programma deve essere diverso da come mi aveva richiesto all'inizio :doh:

Allego una foto dove si vede la griglia che devo realizzare:

http://img387.imageshack.us/img387/296/audiometria002ml2.jpg (http://imageshack.us)

In pratica con un apparecchio si emettono dei suoni a varie frequenze e si stabilisce la perdita in decibel di udito al variare delle frequenza del suono.

1) Si parte dalla frequenza 1000, 1500, 2000.....8000 poi 500 e 250.
Dovrei permettere di inserire da linea di comando i valori di perdita
misurati e il programma dovrebbe disegnare il valore sulla griglia : puntino
per orecchio destro, croce per orecchio sinistro
3) Puntini e crocette non vanno nelle celle ma sulle colonne delle varie
frequenze; pallino e crocetta possono anche sovrapporsi
4) Alla fine i punti devono essere interpolati da una curva
5) In base al numero di punti che stanno nelle aree A, B, C, D, E e F si
stabilisce il grado di perdita di udito

E' molto piu complicato del previsto ? Il codice postato non si puo riutilizzare ?

spillo491
18-04-2007, 16:43
Ho scritto il codice per l'inserimento dei valori:



InputStreamReader reader = new InputStreamReader (System.in);
BufferedReader myInput = new BufferedReader (reader);

int valore1000, valore2000, valore3000, valore4000, valore6000,
valore8000, valore500, valore250;

try {
System.out.print ("\nPerdita in decibel a 1000 Hz ? ");
valore1000 = Integer.parseInt(myInput.readLine());
System.out.print ("\nPerdita in decibel a 2000 Hz ? ");
valore2000 = Integer.parseInt(myInput.readLine());
System.out.print ("\nPerdita in decibel a 3000 Hz ? ");
valore3000 = Integer.parseInt(myInput.readLine());
System.out.print ("\nPerdita in decibel a 4000 Hz ? ");
valore4000 = Integer.parseInt(myInput.readLine());
System.out.print ("\nPerdita in decibel a 6000 Hz ? ");
valore6000 = Integer.parseInt(myInput.readLine());
System.out.print ("\nPerdita in decibel a 8000 Hz ? ");
valore8000 = Integer.parseInt(myInput.readLine());
System.out.print ("\nPerdita in decibel a 500 Hz ? ");
valore500 = Integer.parseInt(myInput.readLine());
System.out.print ("\nPerdita in decibel a 250 Hz ? ");
valore250 = Integer.parseInt(myInput.readLine());
}
catch (IOException e) {

System.out.println ("Si è verificato un errore: " + e);
System.exit(-1);
}

......avvio interfaccia grafica.....

jappilas
18-04-2007, 16:56
Purtroppo mio padre che mi aveva "commissionato" il lavoro si è accorto che il programma deve essere diverso da come mi aveva richiesto all'inizio :doh: ottimo ... :)
cioè, che i requisiti funzionali del prodotto SW cambino in corso d' opera è tutto meno che infrequente: se sei un giovane aspirante professionista in questo settore, devi essere pronto a fare i conti con questo genere di situazione, quindi è un bene che ti sia capitato di entrare in contatto con questo genere di situazione, fin da ora... ;)
...cut...
E' molto piu complicato del previsto ? Il codice postato non si puo riutilizzare ?molto più complicato, no
però dovrai comunque apportare cambiamenti, nel modo di plottare i singoli punti (per il diverso allineamento, ma soprattutto per la non linearità dell' asse delle ascisse effettive *) e di disegnare la curva interpolante (di nuovo per via dell' andamento non lineare)

* da quel grafico non è molto chiaro che genere di andamento abbia la scala dell' asse delle ascisse: la distanza tra il punto a 8000 e quello a 6000 e tra 6000 e 4000 è pari a quella tra 4000 e 3000, tra 3000 e 2000, e più indietro, 1000 e 750, quindi non mi pare nemmeno logaritmica
è fondamentale, che ti abbia perfettamente chiaro quale sia l' andamento all' interno di ogni intervallo e il criterio di arrotondamento (visto che mi pare di capire tu non plotterai mai "tra" una colonna e l' altra ma solo in corrispondenza del valore più vicino

PGI-Bis
18-04-2007, 16:58
La linea di comando la lascerei dove sta: nei libri di storia.

Il codice che abbiamo esaminato serve a rappresentare graficamente una matrice di valori interattiva. Può servire o non servire, dipende da come decidi ci procedere. Dall'immagine che incolli direi che può servire.

Comunque sia, qui il problema è che devi mettere il PC da parte e progettare la tua applicazione.

Il codice che incolli relativo all'inserimento dati da linea di comando è inutile se prima non stabilisci quale ruolo giocherà il componente che definisce quel comportamento nel sistema. Chi richiede il servizio di inserimento dei dati, quando lo richiede, dove vanno a finire i dati, esistono dei requisiti preliminari all'inserimento... eccetera.

Il comportamento del sistema e un'idea circa le parti di cui è composto lo ottieni dal risultato dell'intervista al committente. Nei cinque punti da te citati c'è già molto e l'immagine rende perfettamente l'idea di quella parte dell'interfaccia che sarà deputata a proiettare il lavoro del programma. Esaminali a fondo, a PC spento.

L'utente inserisce il valore di perdita per una certa frequenza. Come realizzi questo inserimento? L'utente dovrà poter scegliere la "frequenza di inserimento" e il programma richiederà la perdita per questa frequenza?
Dove finiscono questi dati? In una griglia del genere da noi esaminato? Come sono rappresentati? Se una stessa misura è fatta ora per un orecchio, ora per l'altro, l'utente dovrà poter indicare quale sia "l'orecchio che si sta misurando"? Come glielo fai indicare? Si fa un solo test per ogni frequenza? L'utente può cambiare i valori precedentemente immessi? Come glielo fai fare?

E via così. Sono centinaia le domande a cui tu devi trovare una risposta prima ancora di poter pensare a come tradurrai in codice le risposte.

spillo491
18-04-2007, 19:27
1)L'utente inserisce il valore di perdita per una certa frequenza. Come realizzi questo inserimento?

Io pensavo da linea di comando, comunque per ogni frequenza (mio padre dice va fatto nell'ordine 1000, 2000,3000,4000,6000,8000,500,250 )
vorrebbe inserire tramite tastiera numerica i valori della perdita in decibel (da 0 a 100). Magari potrei fare a destra della griglia una tabella con
frequenza e perdita corrispondente per orecchio dx e sx in cui i valori siano modificabili. Poi sotto un pulsante "disegna" che fa disegnare i punti sulla griglia


2)Dove finiscono questi dati? In una griglia del genere da noi esaminato?

Questi dati che quindi hanno un valore di ascissa = frequenza e un valore di ordinata = perdita devono essere plottati su una griglia come quella in figura
Orecchio dx = cerchio vuoto
Orecchio sx = crocetta
Visto che orecchio sx e dx possono dare le stesse misure per una data frequenza pallino e crocetta devono potersi sovrapporre.
Il fatto che la distanza tra freq 750 e 1000 = distanza tra freq 4000 e 6000 è giusto nel senso che è fatto apposta (non so perchè)

3)Si fa un solo test per ogni frequenza?

Si, uno per ogni orecchio

4) L'utente può cambiare i valori precedentemente immessi? Come glielo fai fare?

Bhe sarebbe utile, magari fare a destra della griglia una tabella con
frequenza e perdita corrispondente per orecchio dx e sx in cui i valori siano modificabili. Poi sotto la tabella un pulsante che dopo aver inserito tutti i dati disegni i simboli sulla griglia.

5) Una volta che ho cerchi e crocette sulla griglia devo tracciare dei segmenti che uniscono i vari simboli dello stesso tipo (pulsante unisci orecchio sx e unisci orecchio dx) tutti i cerchi e le crocette con due linee di colore diverso. Devo poter vedere o solo curva orecchio dx o solo curva orecchio sx o tutte e due di colore diverso.

6) Per valutare il deficit si devono guardare le frequenze 500, 1000, 2000, 3000, 4000, 6000. Quindi ho 6 simboli (cerchi o croci) per ogni orecchio.
Il deficit si puo valutare a partire dai dati e non dalla griglia (che serve solo a scopo comunicativo esterno):

es

Se ho 4 simboli nella zona A e altri 2 in C,B e D ho un deficit di primo grado
Se ho 3 simboli nella zona A e altri 3 in C,D,E,F,G ho un deficit di grado due
ecc...
Questo si puo fare con una serie di if credo


Ragazzi scrivendo queste cose mi rendo conto che è un casino :mc:

PGI-Bis
18-04-2007, 20:14
Farò finta di non aver sentito il termine "plottare". :D

Le domande erano per darti un'idea di come si arrivi dai requisiti ad un'idea di programma. Devi dare una risposta a te stesso, non a noi.

Continua ad esplorare l'idea del committente a colpi di domande e risposte dalle quali scaturiranno altre domande.

Credo che la griglia possa tranquillamente disegnarsi man mano che l'utente inserisce i dati (MVC?). Così eviti un gesto dell'utente. Per l'inserimento dei dati potresti usare uno wizard? O possiamo pensare ad un meccanismo di interazione dell'utente con la griglia? Perchè inserire i valori in decibel con la tastiera quando l'utente può cliccare sulla griglia in corrispondenza del valore? Si potrebbero usare delle barre di scorrimento come modificatori dei valori per i decibile? Click sulla griglia nella colonna delle frequenze, appare una barra di scorrimento verticale con un pulsantino "ok", l'utente trascina la barra sul valore in dB rilevato, preme ok e nella griglia compare l'etichetta. Guarda mamma, senza la tastiera! :D.

spillo491
18-04-2007, 20:33
Non ti piace il termine plottare ? :mbe: Certo non credo sia italiano...

Adesso vedrò di studiarmi un po la grafica in java e penso un po sul da farsi !
Conoscete il libro JAVA 2 di horstmann ? E' un buon libro?
Link dove guardarmi quello che serve per fare questo programma?

Grazie

spillo491
19-04-2007, 13:09
Il commitente vorrebbe una cosa di questo tipo per l'inserimento dei dati

http://img220.imageshack.us/img220/3628/immagineda6.png (http://imageshack.us)

Devo usare la classe JTextField?

PGI-Bis
19-04-2007, 13:20
Lì ci sono JLabel, JTextField con un Document che accetta formati numerici, inseriti in un JPanel con un GridBagLayout. Ricorda che mentre pensi a come far apparire un pezzo dell'interfaccia devi anche ragionare su come quel pezzo dialogherà con il resto del programma. Cosa succede mentre l'utente digita i valori (la griglia si aggiorna), quel pezzo di interfaccia permane o appare a richiesta... domande, domande...

spillo491
19-04-2007, 16:37
Vorrei che questo form di inserimento dati restasse sulla destra; sulla sinistra deve essereci la famosa griglia e al centro un bottone "CALCOLA DIAGNOSI".

Sono riuscito a realizzare la parte grafica usando Border Layout e mi viene una cosa del tipo

http://img57.imageshack.us/img57/4597/esbr2.jpg (http://imageshack.us)

Come faccio ad inserire la griglia sulla sinistra e a collegare numeri che inserisco con cerchietti e crocette sulla griglia ? Qui inizia il bello e non so da che parte iniziare

PGI-Bis
19-04-2007, 17:05
Qui non ti posso aiutare. Dovrei fare appello alle mie conoscenze di programmazione orientata agli oggetti che divergono assolutamente dalle teorie consolidate. E non voglio portarti con me nel baratro :D.

La soluzione, e già sto rischiando grosso, sta nel mettere in comunicazione l'oggetto che si occupa di gestire l'inserimento dei dati a sinistra con quello che li rappresenta a destra.

spillo491
19-04-2007, 17:09
Non capisco cosa vuoi dire :help:

PGI-Bis
19-04-2007, 17:20
Lo so, lo so :cry: .

spillo491
19-04-2007, 18:55
:muro: :muro: non so da dove cominciare e da quanto ho capito è sbagliato pure quel poco che ho fatto....è troppo difficile :cry:

PGI-Bis
19-04-2007, 20:14
Quello che hai fatto non è sbagliato è solo che stai interpretando le cose in un modo che non è proprio del tuo punto di vista umano. Tu osservi il problema dal punto di vista del linguaggio di programmazione Java e delle sue librerie. Quello che devi fare è, invece, dire le cose come stanno secondo te e piegare il linguaggio e le librerie ad una mera traduzione di quello che osservi.

Scrivi quello che vedi e poi riempi i buchi con i dettagli del linguaggio. Ad esempio se io, essere umano, dico che quando premo il pulsante OK sul pannello di sinistra appare una croce sulla griglia a destra allora io, essere umano, scrivo in un linguaggio orientato agli oggetti, ad esempio Java ma vale per C++, C# Smalltak Python e qualsiasi altra lingua che supporti la prospettiva orientata agli oggetti:

public class PannelloDiSinistra {

public void pulsanteOkPremuto() {
griglia.inserisciCroce(...
}
}

Questo è quello che ho "visto". Il resto è un dettaglio di realizzazione. Da dove viene la "griglia"? Be', se osservo una stanza e vedo una sedia e un tavolo io neppure mi chiedo da dove vengano il tavolo e la sedia: so solo che essi esistono in un medesimo contesto. E allora:

public class PannelloDiSinistra {
private Contesto contesto;

public PannelloDiSinistra(Contesto c) {
contesto = c;
}

public void pulsanteOkPremuto() {
contesto.getGriglia().inserisciCroce(...
}
}

Cattura meglio l'osservazione che ogni oggetto frutto di un'unica osservazione appartiene al medesimo contesto una cosa tipo:

public abstract class Oggetto {
private Contesto contesto;

public Oggetto(Contesto c) {
this.contesto = c;
}

public Contesto getContesto() {
return contesto;
}
}

public class PannelloDiSinistra extends Oggetto {
public PannelloDiSinistra(Contesto c) {
super(c);
}

public void pulsanteOkPremuto() {
getContesto().creaCrocetta(..., ..., ...); //ad esempio
}
}

Riesci a seguirmi? Il problema che fronteggi ora non è una questione di linguaggio o di libreria ma di espressione dell'idea che hai del programma. Sai come funzionano i pulsanti, sai come creare delle classi, sai come usare una griglia ma non riesci ad esprimere la visione completa del sistema, l'articolazione delle sue parti, il ruolo che ognuna di queste gioca in autonomia e in collaborazione.

Sto vaneggiando troppo? :D E' la parte migliore della programmazione, questa. Pensa che mentre ne scrivo agito le mani come se fossi su un oratore su un palco :D

spillo491
19-04-2007, 20:44
Il fatto è che io fino a pochi giorni fa ho scritto solo programmi java da linea di comando molto semplice mentre di grafica non ho mai scritto nessuna applicazione. Ho voluto lanciare questa sfida con mio padre ma dal tuo ultimo messaggio mi rendo conto che forse mi mancano dei concetti base.

Per prima cosa credo dovrei capire le classi che sono necessarie e che poi dovrò andare ad implementare:

1) classe Griglia
2) classe Simbolo
3) classe Pannello Inserimento Dati
4) classe Disegna simboli su Griglia
5) classe CalcolaDiagnosi (?)
6) classe Principale (dove ho il main)

PGI-Bis
19-04-2007, 21:01
Pensa a quello che fanno, non a come dovrai farglielo fare. Come fai, ad esempio, a far comunicare il Pannello Inserimento Dati con la Griglia? Non dal punto di vista del linguaggio di programmazione. Cioè qual comportamenti e quali proprietà devono avere Griglia e Pannello per poter comunicare (nel senso di scambiarsi informazioni e reagire a questi scambi). Insisto su questo punto perchè una volta che riesci a vedere il rapporto tra due oggetti è bell'e che finita, tutto il resto diventa una bazzeccola.

spillo491
19-04-2007, 21:09
Grazie PGI ho capito, domani ci provo

spillo491
20-04-2007, 10:01
Ho cercato di capire quali sono le caratteristiche che legano la Griglia e il Pannello Inserimento Dati senza pensare al linguaggio di programmazione; le scrivo qui sotto così le ho scritte e se hai voglia mi dici che ne pensi :read:

Classe Griglia

caratteristiche:
frequenza (250,500,750,1000,1500,2000,3000,4000,6000,8000)
perdita in decibel (10,20, 25 ,30,40,50, 55 ,60,70,80,90,100)
simboli (cerchi/croci) su colonne corrispondenti alle varie frequenze; simboli si devono poter sovrappporre
per unire simboli dello stesso tipo con segmenti devo avere le loro coordinate


Classe PannelloInserimentoDati

caratteristiche:
frequenze (250,500,1000,2000,3000,4000,6000,8000)
serie di coppie (frequenza, misura orecchio dx)
serie di coppie (frequenza, misura orecchio sx)
queste coppie mi danno le coordinate dei punti che devo disegnare sulla griglia


Classe DisegnaSimboliSuGriglia

ha bisogno delle coppie di coordinate accennate sopra e deve tener conto che i simboli devono finire sulle linne verticali corrispondenti alle varie frequenze

Classe CalcolaDiagnosi

In base alla disposizione dei simboli dello stesso tipo sulla griglia, quindi in base alle loro coordinate (che però posso avere anche dal Pannello Inserimento Dati) e alla definizione delle aree A,B,C.... calcolo la diagnosi
Ad esempio la zona A rapppresenta un rettangolo che va dalla freq 500 alla freq 2000 e dalla perdita 0 alla perdita 25.

Ho fatto bene o devo andare di piu nel dettaglio? Adesso ho le idee un po piu chiare ma realizzare questo non mi sembra ancora facile, forse perchè non conosco bene le varie classi grafiche/eventi e i loro metodi ?

PGI-Bis
20-04-2007, 12:19
Va bene se riesci a vedere le relazioni che quelle descrizioni creano. Ad esempio io vedo che DisegnaSimboliSuGriglia usa (ha bisogno di) PannelloInserimentoDati e Griglia. CalcolaDiagnosi usa Griglia e/o PannelloInserimentoDati. Usa nel senso più comune del termine.

Tieni conto che questa faccenda di qualcuno che usa qualcun'altro è traducibile (in tanti modi ma anche) attraverso una coppia di metodi set/get. Cioè la classe DisegnaSimboliSuGriglia avrà dei metodi tipo:

setGriglia: unaGriglia
griglia := unaGriglia.

getGriglia
↑griglia.

setPannelloInserimentoDati: unPannelloInserimentoDati
pannelloInserimentDati := unPannelloInserimentoDati.

getPannelloInserimentoDati
↑pannelloInserimentoDati.

Non è l'unica forma possibile (potresti anche passare pannello e griglia al costruttore di DisegnaSimboliSuGriglia) ma è forse la più evidente. Una conseguenza di questa testimonianza d'uso è anche la soluzione al problema da cui eravamo partiti: come faccio a trasformare i dati contenuti nel PannelloInserimentoDati in simboli sulla Griglia. Bene, secondo il tuo schema, quando l'utente premerà il pulsante o digiterà le cifre o interagirà nel modo che riterrai più opportuno userai un oggetto DisegnaSimboliSuGriglia il quale preleverà i dati dal pannelloInserimetoDati e li trasformerà in comandi di disegno per la griglia. Mi segui?

spillo491
23-04-2007, 10:01
Rieccomi qui a stressare un po :)

Relazioni tra le classi :


Classe Griglia usa Classi Simbolo e PannelloInserimentoDati
Classe Simbolo è a se stante
Classe PannelloInserimentoDati è a se stante
Classe DisegnaSimboliSuGriglia usa classi PannelloInserimentoDati, Griglia e Simbolo
Classe CalcolaDiagnosi usa classi Simbolo e Griglia o PannelloInserimentoDati


Non sono sicuro che la classe CalcolaDiagnosi sia necesssaria; sui libri dicono che le classi rappresentano oggetti e sono indicate da sostantivi mentre sono i metodi che compiono azioni e che sono indicati da verbi

spillo491
23-04-2007, 10:16
.....secondo il tuo schema, quando l'utente premerà il pulsante o digiterà le cifre o interagirà nel modo che riterrai più opportuno userai un oggetto DisegnaSimboliSuGriglia il quale preleverà i dati dal pannelloInserimetoDati e li trasformerà in comandi di disegno per la griglia.

Qual è il più semplice da implementare ?

spillo491
23-04-2007, 10:22
Inizio a buttare giù qualcosa :


public class Griglia {

public Griglia(Simbolo simbol, PannelloInserimentoDati pid){

}
}



public enum Simbolo {
VUOTO,
PALLINO,
CROCE
}



public class DisegnaSimboliGriglia {

public DisegnaSimboliGriglia(Simbolo simbol, Griglia grid,
PannelloInserimentoDati pid){

}
}



public class CalcolaDiagnosi {

public CalcolaDiagnosi (Simbolo simbol, PannelloInserimentoDati pid){

}
}


La classe PannelloInserimentoDati ha il costruttore vuoto cioè senza parametri

PGI-Bis
23-04-2007, 11:34
Il più semplice da realizzare è quello che meglio corrisponde a ciò che osservi dal tuo punto di vista. In fondo l'orientamento agli oggetti è tutto qui. Ora sono un po' alle strette, se puoi aspettare fino a stasera butto giù due righe ed un esempio di come vedo io questo programma, in modo che tu abbia una linea guida e qualcosa a cui fare riferimento per scriverlo.

spillo491
23-04-2007, 11:51
Il più semplice da realizzare è quello che meglio corrisponde a ciò che osservi dal tuo punto di vista. In fondo l'orientamento agli oggetti è tutto qui.

Giusto, me lo avevi già detto !
Grazie dell'aiuto che mi stai dando, di passione per la programmazione ne devi avere tanta per seguirmi come stai facendo.

PGI-Bis
23-04-2007, 15:36
Stavo pensacchiando un po' alla faccenda. E m'è venuto un dubbio. I valori rappresentati nella griglia sono continui o discreti? Cioè cosa succede se lo strumento rileva che l'utente a 250hz perde 13 decibel? La griglia deve riportare 13 decibel oppure deve approssimare a 10?

spillo491
23-04-2007, 16:23
Devo chiedere al babbo appena arriva :D

spillo491
23-04-2007, 17:41
Si possono avere solo multipli di 5 (5,10,15,20,25.....)

PGI-Bis
23-04-2007, 23:27
Abbi pazienza che 'sto componendo l'iliade. Sto scrivendo il programma tenendo una specie di "diario" di quello che penso, di come lo traduco in codice, dei ripensamenti, degli errori eccetera. Insomma, una specie di auto-psicanalisi :D. L'azzardata idea che sta dietro questa apparente follia è che leggendo come concretamente uno (io) crea un programma, non rifacendosi ad astratti volumi ma raccontando i passaggi "veri", uno per uno, stupidaggini comprese, sia possibile rendersi conto del processo pratico e, magari, formarne uno proprio.

Magari alla fine non ci si capisce una fava (veramente sto scrivendo quello che mi salta in mente mentre scrivo l'applicazione) ma è un esperimento piuttosto divertente :D. Penso che lo finirò domani sera.

spillo491
23-04-2007, 23:29
Grazie ancora

PGI-Bis
24-04-2007, 23:09
Praticamente c'è voluto un volume di ingegneria navale per creare la griglia:

http://www.tukano.it/audiogriglia.PNG

Però è venuta fichissima :D

Ancora un po' di pazienza e ti fornisco il malloppo. Occhio però che sono 68 pagine di farfugliamenti, errori, ripensamenti... tutto documentato :D.

PGI-Bis
25-04-2007, 01:11
Sono arrivato al collegamento tra la griglia e il pannello di inserimento dati. Mi fermo perchè mi sono detto "e se poi non ci si capisce una fava?" Gli appunti che ho preso durante la creazione sono proprio "appunti di cosa penso quando programmo". E' un esperimento che volevo fare da tempo. Sono curioso di sapere se si colga un senso del procedimento oppure risultino essere solo farfugliamenti. Qui c'è lo zip:

tutorial.zip (http://www.tukano.it/tutorial.zip)

dentro c'è un PDF con le 72 pagine del "diario". Nella cartella src ci sono i sorgenti. Non li ho commentati di proposito. A parte il fatto che sono scritti in "italianJava" (Audiogramma, aggiungiAscoltatoreEventi, calcolaLarghezzaEtichetteFrequenze e via dicendo :D), pià del codice conterebbe, nel mio malsano proposito, rendere l'idea di come quel codice sia saltato fuori.

Prova a dargli un'occhiata. Se ti pare di capire come funziona il giochino, continuo. Altrimenti proviamo un'altra strada. Comunque è un programma molto divertente da fare.

spillo491
25-04-2007, 08:33
Grazie PGI oggi mr lo guardo con calma :)

spillo491
26-04-2007, 10:39
Ciao PGI ho inziato a leggere il tuo diario e devo dire che anche se ci sono alcune cose che non mi sono molto chiare è molto utile vedere come hai ragionato per scrivere il codice e seguire il tutto passo-passo. Sicuramente questo diario mi è moolto utile!

Ad esempio che significa questa sintassi ?

ArrayList<Decibel> righe = new ArrayList<Decibel>();
ArrayList<Frequenza> colonne = new ArrayList<Frequenza>();

lovaz
26-04-2007, 10:42
Ha dichiarato e allocato due liste (vuote), una di oggetti di tipo Decibel,
e una di oggetti di tipo Frequenza.

PGI-Bis
26-04-2007, 11:02
Se guardi nella documentazione Java vedrai che alcune classi e interfacce hanno dei nomi come:

Pippo<T>

oppure

Pippo<K, E>

Sono classi generiche. Quando usi quelle classi o quelli interfacce devi mettere qualcosa al posto delle lettere maiuscolo: quel qualcosa è il nome di un tipo (classe, interfaccia o enumerativo). La specificazione di un tipo è detta dichiarazione di parametro e la dichiarazione di parametro per un tipo generico crea un tipo parametrico.

Dunque dato il tipo generico ArrayList<T> la dichiarazione di parametro "Decibel" crea il tipo parametrico ArrayList<Decibel>.

ArrayList<Decibel> è quindi la dichiarazione di un tipo parametrico.

Sottolineo che per tipo intendo classe, interfaccia o enumerativo (non int, boolean, char ad esempio).

Un tipo parametrico è un tipo di operatore su un tipo. E' una categoria di oggetti che fa qualcosa avendo a disposizione dei dati appartenenti al tipo dichiarato come parametro.

Un operatore...opera. Fa delle operazioni. L'operazione che un tipo parametrico ArrayList<Decibel> fa sugli oggetti Decibel è il contenimento. Come giustamente dice Lovaz, ArrayList<Decibel> è una lista, nel senso della struttura dati, di Decibel, cioè che contiene valori di tipo Decibel.

Direi che è tutto qui.

spillo491
26-04-2007, 11:39
Qui dichiari un Arraylist di ArrayList di oggetti Decibel e lo chiami dati giusto ?

private ArrayList<ArrayList<Decibel>> dati =

%%%%%%%%%%%%%%%%%%%%%%%%%

E invece questo ?

public class Griglia {

Map<GridKey, Simbolo> dati...
}

spillo491
26-04-2007, 13:15
No nulla, ho capito :D

spillo491
26-04-2007, 16:08
Questa parte di codice in rosso che cosa fa?

public GrigliaSimboli(Collection<Decibel> valoriRighe, Collection<Frequenza>
valoriColonne) {

simboli = new Simbolo[numeroDiRighe * numeroDiColonne];
numeroDiRighe = valoriRighe.size();
numeroDiColonne = valoriColonne.size();
int indice = 0;
for(Decibel d : valoriRighe) {
indiciRighe.put(d, indice);
indice++;
}

Thanks

PGI-Bis
26-04-2007, 16:18
E' un ciclo for-each, un "addolcimento sintattico" per la forma reale:

Iterator<Decibel> iteratore = valoriRighe.iterator();
while(iteratore.hasNext()) {
Decibel d = iteratore.next();
fai qualcosa con d
}

Cioè quella roba qui sopra è (quasi) uguale a:

for(Decibel d : valoriRighe) {
fai qualcosa con d
}

Letterariamente sarebbe da leggersi come "per ogni Decibel d in valoriRighe...".

PGI-Bis
26-04-2007, 16:22
dimenticavo il resto. La linea

indiciRighe.put(d, indice)

associa nella mappa indiciRighe il Decibel d al valore Integer indice (indice è un int ma l'autoboxing lo converte in Integer). La linea successiva incrementa il valore di indice.

Lo scopo di quelle righe è costruire una mappa che associa ogni Decibel ad una riga dove la riga è conservata come "riga di indice tot".

spillo491
26-04-2007, 18:39
Perfetto !
Prima di provare il programma volevo capire la fase di progettazione e di stesura di tutto il codice ma oggi volevo dare una sbirciatina al risultato; il problema è che nei file java che mi hai mandato ci sono solo caratteri incomprensibili. Che può essere ?

Un altra cosa:
L'audiogramma non è una matrice bidimensionale ma tridimensionale:[decibel][frequenza][simboli] Questo perché in un punto della griglia posso avere due simboli sovrapposti ?

PGI-Bis
26-04-2007, 19:05
Io uso la codifica UTF-16 per i sorgenti Java. Forse è per quello.

Yesss, per tridimensionale intendevo esattamente quello.

spillo491
26-04-2007, 19:34
Che editor mi consigli di usare; io sto usando EDITEUR ma non è un gran che :muro:

PGI-Bis
26-04-2007, 19:52
Puoi tranquillamente usare blocco note, basta che specifichi Unicode come codifica nella finestra di selezione del file da aprire.

spillo491
27-04-2007, 11:22
"
Creo un pannello poi gli passo un audiogramma e il pannello adatta la sua interfaccia alla lista di frequenze dell'audiogramma. Cioè il pannello, in base ad un audiogramma, crea da solo il numero necessario di caselle combinate e collega da solo le azioni prodotte da queste caselle alle mutazioni corrispondenti nell'audiogramma. Come dovrebbe essere fatto un pannello del genere?

1. quando imposto l'audiogramma attraverso il metodo setAudiogramma di questo ipotetico
pannello
2. il pannello prende la lista di valori in decibel che formano le righe dell'audiogramma
3. il pannello prende la lista di frequenze dall'audiogramma
4. per ogni frequenza, il pannello genera 2 caselle combinate
5. i valori di queste caselle combinate sono (vuoto)+(i vari decibel)
6. il pannello aggiunge alle caselle combinate un ascoltatore di eventi (ActionEvent per una
JComboBox) attraverso il quale io determino quali sono i valori decibel, frequenza e
simbolo da usare per impostare un simbolo nell'audiogramma.

"

Però non è detto anzi è sicuro che non devo inserire valori per tutte le frequenze che ci sono nella griglia. Magari faccio misurazioni per 1000 Hz e poi per 2000 Hz. Per 1500 Hz dovrò selezionare null nel pannello inserimento dati ?

PGI-Bis
27-04-2007, 11:31
Sebbene io pensassi che l'utente avrebbe dovuto inserire tutti i valori per tutte le frequenze, l'esistenza di un valore "non rilevato" (che è poi null tra i valori Decibel accettati dall'audiogramma) consente di non immettere i rilevamenti per ogni frequenza.

Quando l'interfaccia si apre, tutte le caselle combinate hanno valore "vuoto". L'utente può immettere (selezionare) solo i valori che ha rilevato per le frequenze che gli interessano.

Prova ad eseguire il programma. Vai nella cartella "src" dello zip con il prompt dei comandi, digita:

java it.audiobla.Main

e premi invio.

spillo491
27-04-2007, 11:40
Ok adesso provo.

In che senso prendo il modello con questa istruzione ?

DecibelComboBoxModel decibelModel = (DecibelComboBoxModel) box.getModel();

PGI-Bis
27-04-2007, 12:01
Secondo l'architettura MVC, un componente è realizzabile attraverso quattro tipi di oggetti:

modello

il modello è un oggetto che contiene le informazioni sullo stato dell'oggetto in un certo istante. Il modello possiede un elenco di oggetti che possono ricevere notifiche. Quando le informazioni contenute nel modello cambiano, il modello invia un messaggio ad ogni oggetto che può ricevere notifiche presente nel suo elenco.

oggetti che possono ricevere notifiche (notifiable, viva l'inglese :D).

e' una categoria di oggetti che ha la capacità di ricevere un messaggio di stato da un modello.

vista

la vista è un oggetto che, dato un modello, lo rappresenta, di solito graficamente. La vista è un oggetto che può ricevere notifiche dal modello.

controllo

il controllo è un oggetto che traduce l'interazione dell'utente con la vista in mutazioni di stato del modello.


I componenti Swing adottano una variante dell'architettura MVC detta SMA. Questa variante ha comunque il concetto di modello e di vista. Cioè per ogni componente Swing esiste un oggetto che ne contiene lo stato ed un oggetto che rappresenta graficamente questo stato.

Il modello del componente JComboBox è ComboBoxModel. C'è anche una vista+controllo, ComboBoxUI, ma a noi interessa il modello. Per accedere al modello di una JComboBox si usa il metodo getModel di questa JComboBox. Che interesse abbiamo ad accedere al modello di una JComboBox? Abbiamo interesse ad accedere a questo modello perchè è nel modello che si trovano le informazioni sullo stato, attuale o possibile, di un componente. Vale a dire che è attraverso il modello, attraverso l'oggetto restituito dal comboBox.getModel(), che possiamo sapere quale sia il valore attualmente selezionato e quali siano gli altri possibili valori. Sempre attraverso il modello possiamo cambiare questi valori ma se non ricordo male è solo per leggere che là accedo al modello.

spillo491
27-04-2007, 13:40
Non riesco a compilare cavolicchio

Compilando il main mi da cento errori:

illegal character : \0 :confused:

Se apro il file con Wordpad sembra in ordine :mbe:

PGI-Bis
27-04-2007, 13:45
Devi specificare la codifica dei sorgenti. Apri la console (prompt dei comandi), vai nella cartella src, digita

javac -d . -encoding utf-16 *.java

e premi invio.

spillo491
27-04-2007, 13:55
Da errore comunque con :

javac -d . -encoding utf-16 *.java
javac Main.java

:muro: :muro:

PGI-Bis
27-04-2007, 14:00
Che errore ti da?

spillo491
27-04-2007, 14:05
Sempre lo stesso comuqnue se apro i file con il blocnote appaiono ancora quegli strani quadrettini mase cerco di incollarlo qui sul forum scompaiono e il codice è perfetto

PGI-Bis
27-04-2007, 14:12
Sei sicuro di aver scritto (solo):

javac -d . -encoding utf-16 *.java

e dato invio?

spillo491
27-04-2007, 14:14
Si e non mi da nessun errore :confused:

PGI-Bis
27-04-2007, 14:18
Ora scrivi:

java it.audiobla.Main

e dai invio. Parte?

spillo491
27-04-2007, 14:22
Mi da un eccezione

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException:
input == null !

PGI-Bis
27-04-2007, 14:29
nella cartella src c'è una sottocartella images. Dentro a quella cartella dovrebbero esserci due file png:

crocetta.png

e

pallino.png

Ci sono?

spillo491
27-04-2007, 14:44
Erano in un altra sottocartella adesso il programma funziona però non riesco a compilare

PGI-Bis
27-04-2007, 16:29
Fai così.

Crea una cartella per il progetto dove vuoi. Copia là dentro tutti i sorgenti e la cartella images con le due icone. Compili, sempre specificando la codifica:

javac -d . -encoding utf-16 *.java

Giusto per chiarire, l'opzione -d specifica dove vuoi che siano generate le cartelle dei package con i loro file class, il punto (.) significa "la cartella di lavoro", -encoding specifica la codifica dei file sorgente e utf-16 è la codifica, *.java significa tutti i file il cui nome finisce per .java presenti nella cartella di lavoro.

Dopo la compilazione vedrai che nella cartella del progetto è creata un directory "it" con dentro una directory "audiobla" e dentro i file class. Per eseguire, usi

java it.audiobla.Main

dove it.audiobla.Main è il nome pienamente qualificato della classe in cui è dichiarato il metodo public static void main. Il nome pienamente qualificato di una classe è il nome della classe preceduto dal nome del package a cui appartiene, con un punto di separazione.

Se incontri un problema di compilazione o esecuzione, incolla sempre nel messaggio la traccia dell'errore riportata nel prompt dei comandi, così è più facile stabilire quale sia il problema.

spillo491
27-04-2007, 19:14
"
Crea una cartella per il progetto dove vuoi. Copia là dentro tutti i sorgenti e la cartella images con le due icone. Compili, sempre specificando la codifica:
"

Ma i file java devo sempre metterli nella cartella bin della cartella java se no non me li riconosce i file

Ecco gli errori che mi da:
^
Main.java:4: illegal character: \0
i m p o r t j a v a x . s w i n g . * ;
^
Main.java:4: illegal character: \0
i m p o r t j a v a x . s w i n g . * ;
^
Main.java:5: illegal character: \0
i m p o r t j a v a . u t i l . * ;
^
Main.java:5: illegal character: \0
i m p o r t j a v a . u t i l . * ;
^
Main.java:5: illegal character: \0
i m p o r t j a v a . u t i l . * ;
^
Main.java:5: illegal character: \0
i m p o r t j a v a . u t i l . * ;
^
Main.java:5: illegal character: \0
i m p o r t j a v a . u t i l . * ;
^
Main.java:5: illegal character: \0
i m p o r t j a v a . u t i l . * ;
^
Main.java:6: illegal character: \0

^
Main.java:7: illegal character: \0
p u b l i c c l a s s M a i n {
^
Main.java:7: illegal character: \0
p u b l i c c l a s s M a i n {
^
Main.java:7: illegal character: \0
p u b l i c c l a s s M a i n {
^
Main.java:7: illegal character: \0
p u b l i c c l a s s M a i n {
^
Main.java:7: illegal character: \0
p u b l i c c l a s s M a i n {
^
Main.java:8: illegal character: \0

^
Main.java:9: illegal character: \0
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g
s ) {
^
Main.java:9: illegal character: \0
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g
s ) {
^
Main.java:9: illegal character: \0
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g
s ) {
^
Main.java:9: illegal character: \0
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g
s ) {
^
Main.java:9: illegal character: \0
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g
s ) {
^
Main.java:9: illegal character: \0
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g
s ) {
^
Main.java:9: illegal character: \0
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g
s ) {
^
Main.java:9: illegal character: \0
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g
s ) {
^
Main.java:9: illegal character: \0
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g
s ) {
^
Main.java:9: illegal character: \0
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g
s ) {

^
Main.java:9: illegal character: \0
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g
s ) {

^
Main.java:9: illegal character: \0
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [ ] a r g
s ) {

^
Main.java:10: illegal character: \0
S w i n g U t i l i t i e s . i n v o k e L a t e r ( n e w R
u n n a b l e ( ) {
^
Main.java:10: illegal character: \0
S w i n g U t i l i t i e s . i n v o k e L a t e r ( n e w R
u n n a b l e ( ) {
^
Main.java:10: illegal character: \0
S w i n g U t i l i t i e s . i n v o k e L a t e r ( n e w R
u n n a b l e ( ) {
^
Main.java:10: illegal character: \0
S w i n g U t i l i t i e s . i n v o k e L a t e r ( n e w R
u n n a b l e ( ) {
^
Main.java:10: illegal character: \0
S w i n g U t i l i t i e s . i n v o k e L a t e r ( n e w R
u n n a b l e ( ) {
^
Main.java:10: illegal character: \0
S w i n g U t i l i t i e s . i n v o k e L a t e r ( n e w R
u n n a b l e ( ) {
^
Main.java:10: illegal character: \0
S w i n g U t i l i t i e s . i n v o k e L a t e r ( n e w R
u n n a b l e ( ) {

^
Main.java:10: illegal character: \0
S w i n g U t i l i t i e s . i n v o k e L a t e r ( n e w R
u n n a b l e ( ) {

^
Main.java:10: illegal character: \0
S w i n g U t i l i t i e s . i n v o k e L a t e r ( n e w R
u n n a b l e ( ) {

^
Main.java:10: illegal character: \0
S w i n g U t i l i t i e s . i n v o k e L a t e r ( n e w R
u n n a b l e ( ) {

^
Main.java:11: illegal character: \0
p u b l i c v o i d r u n ( ) {
^
Main.java:11: illegal character: \0
p u b l i c v o i d r u n ( ) {
^
Main.java:11: illegal character: \0
p u b l i c v o i d r u n ( ) {
^
Main.java:11: illegal character: \0
p u b l i c v o i d r u n ( ) {
^
Main.java:11: illegal character: \0
p u b l i c v o i d r u n ( ) {
^
Main.java:11: illegal character: \0
p u b l i c v o i d r u n ( ) {
^
Main.java:11: illegal character: \0
p u b l i c v o i d r u n ( ) {
^
Main.java:11: illegal character: \0
p u b l i c v o i d r u n ( ) {
^
Main.java:11: illegal character: \0
p u b l i c v o i d r u n ( ) {
^
Main.java:11: illegal character: \0
p u b l i c v o i d r u n ( ) {
^
Main.java:12: illegal character: \0
n e w M a i n ( ) . s t a r t ( ) ;
^
Main.java:12: illegal character: \0
n e w M a i n ( ) . s t a r t ( ) ;
^
Main.java:12: illegal character: \0
n e w M a i n ( ) . s t a r t ( ) ;
^
Main.java:12: illegal character: \0
n e w M a i n ( ) . s t a r t ( ) ;
^
Main.java:12: illegal character: \0
n e w M a i n ( ) . s t a r t ( ) ;
^
Main.java:12: illegal character: \0
n e w M a i n ( ) . s t a r t ( ) ;
^
Main.java:12: illegal character: \0
n e w M a i n ( ) . s t a r t ( ) ;
^
Main.java:12: illegal character: \0
n e w M a i n ( ) . s t a r t ( ) ;
^
Main.java:12: illegal character: \0
n e w M a i n ( ) . s t a r t ( ) ;
^
Main.java:12: illegal character: \0
n e w M a i n ( ) . s t a r t ( ) ;
^
Main.java:12: illegal character: \0
n e w M a i n ( ) . s t a r t ( ) ;
^
Main.java:12: illegal character: \0
n e w M a i n ( ) . s t a r t ( ) ;
^
Main.java:13: illegal character: \0
}
^
Main.java:13: illegal character: \0
}
^
Main.java:13: illegal character: \0
}
^
Main.java:13: illegal character: \0
}
^
Main.java:13: illegal character: \0
}
^
Main.java:14: illegal character: \0
} ) ;
^
Main.java:14: illegal character: \0
} ) ;
^
Main.java:14: illegal character: \0
} ) ;
^
Main.java:14: illegal character: \0
} ) ;
^
Main.java:14: illegal character: \0
} ) ;
^
Main.java:14: illegal character: \0
} ) ;
^
Main.java:15: illegal character: \0
}
^
Main.java:15: illegal character: \0
}
^
Main.java:15: illegal character: \0
}
^
Main.java:16: illegal character: \0

^
Main.java:17: illegal character: \0
p r i v a t e v o i d s t a r t ( ) {
^
Main.java:17: illegal character: \0
p r i v a t e v o i d s t a r t ( ) {
^
Main.java:17: illegal character: \0
p r i v a t e v o i d s t a r t ( ) {
^
Main.java:17: illegal character: \0
p r i v a t e v o i d s t a r t ( ) {
^
Main.java:17: illegal character: \0
p r i v a t e v o i d s t a r t ( ) {
^
Main.java:17: illegal character: \0
p r i v a t e v o i d s t a r t ( ) {
^
Main.java:17: illegal character: \0
p r i v a t e v o i d s t a r t ( ) {
^
Main.java:17: illegal character: \0
p r i v a t e v o i d s t a r t ( ) {
^
Main.java:18: illegal character: \0
C o l l e c t i o n < F r e q u e n z a > f r e q u e n z e
= U t i l s . c r e a I n s i e m e F r e q u e n z e (
^
Main.java:18: illegal character: \0
C o l l e c t i o n < F r e q u e n z a > f r e q u e n z e
= U t i l s . c r e a I n s i e m e F r e q u e n z e (
^
Main.java:18: illegal character: \0
C o l l e c t i o n < F r e q u e n z a > f r e q u e n z e
= U t i l s . c r e a I n s i e m e F r e q u e n z e (
^
Main.java:18: illegal character: \0
C o l l e c t i o n < F r e q u e n z a > f r e q u e n z e
= U t i l s . c r e a I n s i e m e F r e q u e n z e (
^
100 errors

PGI-Bis
27-04-2007, 20:02
No, i file non devi metterli nella cartella bin della piattaforma Java. I file class li lasci nella cartella del programma che crei.

L'errore che riporti è dovuto alla mancata impostazione della codifica del file durante la compilazione. Quando compili i file che ti ho dato devi dire al compilatore che sono codificati in utf-16 usando l'opzione -encoding utf-16.

Ripeto: non devi mettere i file class nella cartella bin del JRE per eseguire il programma che rappresentano.

PGI-Bis
27-04-2007, 20:04
P.s: forse è meglio se scarichi Netbeans. E' un IDE per Java

http://www.netbeans.info/downloads/index.php

spillo491
27-04-2007, 20:54
Azz quando cerco di installarlo mi da un errore

No java Development Kit (JDK) was found on thi system

Non ci capisco piu nulla, ho sempre compilato senza problemi

spillo491
27-04-2007, 21:40
Ho installato JDK 1.5.0 e adesso ho installato netbeans

Io ho impostato la codifica dei file con javac -d . -encoding utf-16 *.java ma nulla da sempre lo stesso errore
Se apro il file main.java con netbeans ne esce una cosa incomprensibile
I file class li ho in una cartella it ma comunque dovrebbero essere il risultato della compilazione, non dovrebbero servire per fare la compilazione stessa

Scusa il casino

spillo491
27-04-2007, 23:24
package it.audiobla;
import java.awt.*;
import javax.swing.*;
import java.util.*;

public class Main {

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Main().start();
}
});
}

private void start() {
Collection<Frequenza> frequenze = Utils.creaInsiemeFrequenze(125, 250, 500, 750, 1000, 1500, 2000, 3000, 4000, 6000, 8000);
Collection<Decibel> decibel = Utils.creaInsiemeDecibel(null, 10, 15, 20, 25, 30, 40, 50, 55, 60, 70, 80, 90, 100);
Audiogramma audiogramma = new Audiogramma(decibel, frequenze);
PannelloInserimentoDati pannelloInserimentoDati = new PannelloInserimentoDati();
pannelloInserimentoDati.setAudiogramma(audiogramma);
GrigliaAudiogramma griglia = new GrigliaAudiogramma(audiogramma);
JFrame finestra = new JFrame("Prova");
finestra.add(pannelloInserimentoDati.getComponent(), BorderLayout.WEST);
finestra.add(griglia, BorderLayout.CENTER);
finestra.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
finestra.pack();
finestra.setVisible(true);
}
}

PGI-Bis
28-04-2007, 01:12
Ti allego i sorgenti in forma di progetto per Netbeans. Occhio che io uso Java 6.

Scompatta lo zip, poi apri Netbeans, scegli "file -> open project" e poi seleziona la cartella "audiobla" estratta dallo zip.

spillo491
28-04-2007, 14:54
Fatto e ora i sorgenti sono codificati in modo corretto. Adesso che faccio ? Posso compilare direttammente da netbeans ?

PGI-Bis
28-04-2007, 15:02
Sì. C'è un pulsante con la freccia (quello senza il quadrato) che se necessario compila e poi esegue. Il pulsante con la scopa elimina i vecchi file class e compila di nuovo tutto. Il pulsante con la chiave inglese compila e basta.

Comunque credo che a te interessi più dei sorgenti capire come farne di tuoi anche perchè il pezzo di programma che ho scritto io è frutto della mia fantasia: sei tu che sai con certezza cosa deve effettivamente fare il programma e come deve farlo. E non è detto che quelle classi possano essere adattate al programma corretto.

spillo491
28-04-2007, 15:12
init:
deps-jar:
Compiling 18 source files to C:\Documents and Settings\Admin\Desktop\audiobla\build\classes
javac: invalid target release: 1.6
Usage: javac <options> <source files>
where possible options include:
-g Generate all debugging info
-g:none Generate no debugging info
-g:{lines,vars,source} Generate only some debugging info
-nowarn Generate no warnings
-verbose Output messages about what the compiler is doing
-deprecation Output source locations where deprecated APIs are used
-classpath <path> Specify where to find user class files
-cp <path> Specify where to find user class files
-sourcepath <path> Specify where to find input source files
-bootclasspath <path> Override location of bootstrap class files
-extdirs <dirs> Override location of installed extensions
-endorseddirs <dirs> Override location of endorsed standards path
-d <directory> Specify where to place generated class files
-encoding <encoding> Specify character encoding used by source files
-source <release> Provide source compatibility with specified release
-target <release> Generate class files for specific VM version
-version Version information
-help Print a synopsis of standard options
-X Print a synopsis of nonstandard options
-J<flag> Pass <flag> directly to the runtime system

BUILD FAILED (total time: 0 seconds)

:mbe:
La cartella audiobla la posso lasciare sul desktop oppure devo metterla nella cartella bin ?

PGI-Bis
28-04-2007, 15:14
Quando ho detto "occhio che io uso Java 6" intendevo "occhio che io uso Java 6" :D.

Scarica e installa Java 6.

spillo491
28-04-2007, 15:15
Ah ecco :stordita:

spillo491
28-04-2007, 15:59
Ho installato JDK 6u1 : jdk-6u1-windows-i586-p.exe
ma mi da ancora

init:
deps-jar:
Compiling 18 source files to C:\Documents and Settings\Admin\Desktop\audiobla\build\classes
javac: invalid target release: 1.6
Usage: javac <options> <source files>
where possible options include:
-g Generate all debugging info
-g:none Generate no debugging info
-g:{lines,vars,source} Generate only some debugging info
-nowarn Generate no warnings
-verbose Output messages about what the compiler is doing
-deprecation Output source locations where deprecated APIs are used
-classpath <path> Specify where to find user class files
-cp <path> Specify where to find user class files
-sourcepath <path> Specify where to find input source files
-bootclasspath <path> Override location of bootstrap class files
-extdirs <dirs> Override location of installed extensions
-endorseddirs <dirs> Override location of endorsed standards path
-d <directory> Specify where to place generated class files
-encoding <encoding> Specify character encoding used by source files
-source <release> Provide source compatibility with specified release
-target <release> Generate class files for specific VM version
-version Version information
-help Print a synopsis of standard options
-X Print a synopsis of nonstandard options
-J<flag> Pass <flag> directly to the runtime system

BUILD FAILED (total time: 1 second)

Che cavolata ho fatto questa volta ? Dovevo installare JDK 6 with Java EE ?

PGI-Bis
28-04-2007, 16:48
apri netbeans, vai nel menu tools -> java platform manager

premi il pulsante add platform

seleziona la cartella in cui hai installato il JDK 6 (c:\programmi\java\jdk1.6.0_01), imposta quella piattaforma come predefinita, chiudi la finestra e ricompila. A questo punto Netbeans sarà in grado di gestire la versione 1.6.

spillo491
28-04-2007, 17:51
chiudi la finestra e ricompila. A questo punto Netbeans sarà in grado di gestire la versione 1.6.

Ricompilo cosa ? Il progetto audiobla ? Non funziona ancora pero se guardi come default è impostato JDK 1.5 ; non riesco a impostare l'altro come default

http://img63.imageshack.us/img63/1314/immagineci2.jpg (http://imageshack.us)

PGI-Bis
28-04-2007, 18:16
Dev'essere un JDK, non il JRE (il nome della cartella in cui è contenuto è "jdk...blabla"). Se è un JDK, rimuovi la versione 5 e sei a posto.

spillo491
02-05-2007, 18:27
Rieccomi, finalmente sono riuscito a installare correttamente netbeans e sono riuscito a compilare ed eseguire l'applicazione.

Eseguendo il programma ho notato che cè una cosa che non va nella griglia: il 25 e il 55 devono stare a meta della distanza tra 20/30 e 50/60. Cioè anche se non si capisce bene dall'immagine della griglia postata nelle pagine precedenti la distanza tra 10,20,30,40,50,60,70,80,90,100 deve essere uguale. la casella tra 20 e 30 e quella tra 50 e 60 va poi divisa in due.
E' complicato da sistemare ?

Poi lel pannello inserimento dati devo poter dare oltre a 25 e 55 anche 5,15,35,45,65,75,85 e 95. Adesso provo a sistemare questa cosa che non mi sembra difficile

PGI-Bis
02-05-2007, 19:13
Per inserire i valori basta infilarli nella collezione di decibel usata per costruire l'audiogramma. Ora è:

Collection<Decibel> decibel = Utils.creaInsiemeDecibel(
null, 10, 15, 20, 25, 30, 40, 50, 55, 60, 70, 80, 90, 100);

tu dirai:

Collection<Decibel> decibel = Utils.creaInsiemeDecibel(
null, 5, 10, 15, 20, 25, 30, 35, 40, 45, eccetera

Per cambiare il disegno della griglia devi manipolare il codice di PainterAudiogramma. La "logica" del disegno da parte di PainterAudiogramma è spiegata negli appunti. Trascurando la parte relativa al disegno degli elementi (intestazioni di riga e di colonna e etichette sparse) il resto è una semplice griglia: tot linee verticali, tot linee orizzontali. A disegnare una linea in mezzo o a non disegnare qualcosa si fa presto.

Nota che PainterAudiogramma è incompleto: manca, in particolare, un metodo che consenta di calcolare le dimensioni del componente a partire dai dati dell'audiogramma e un insieme di attributi di rendering (font, altezza delle righe, larghezza delle colonne eccetera). Ora c'è un forfait di 600x600 pixel ma quella misura va tolta e determinata dinamicamente. Comunque conta avere un'idea della struttura del programma che, tra l'altro, è solo una delle possibili.

spillo491
04-05-2007, 10:16
Ho modificato le caselle combinate in modo da poter scegliere tutti i multipli di 5 ma in questo modo mi compaiono anche sulla griglia i vari 5, 15, 35, 45... che non devono esserci. Adesso comunque sto leggendo i tuoi appunti e sono arrivato alla spiegazione del Paintergriglia per cercare di capire come modificarla

Negli appunti ho trovato cose del tipo

PERDITA IN DECIBEL
H
W
(0, 0)
x=w/2
wd
hd
FREQUENZA Hz
x=w/2
125 250 500 ...
Wf

Non riesco a capire cosa significa questa lista

PGI-Bis
04-05-2007, 10:41
Sono coordinate o dimensioni o etichette.

Prendi il disegno di pagina 36.

Il rettangolo con dentro la scritta "PERDITA IN DECIBEL" rappresenta l'etichetta "PERDITA IN DECIBEL" che si vede sul disegno che hai incollato nel forum.

Il valore (0, 0) collegato con una freccia nera all'angolo superiore sinistro dell'etichetta "PERDITA IN DECIBEL" sta a significare che a quell'angolo superiore sinistro corrisponderà il punto di coordinate (0, 0)...

Azz. Mi sono accorto solo adesso che Open Office m'ha sballato tutti i disegni. Ma vaff... :mad:

Aspetta che li metto a posto...

PGI-Bis
04-05-2007, 11:35
Oook. Fatto

pdf aggiornato (http:\\www.tukano.it\diary.pdf)

Ora che le etichette corrispondono alle linee di quotatura e le che le linee di quotatura corrispondono agli spazi, la cosa dovrebbe essere comprensibile :D.

spillo491
04-05-2007, 12:13
Mitico grazie

spillo491
04-05-2007, 17:34
Due domande:


Che significa il parametro di questo metodo "int.....values" ?
public static Collection<Decibel> creaInsiemeDecibel(int...values)
Perchè hai definito i Decibel e le Frequenze come oggetti ArrayList e non array di interi ? Per poter inserire anche il valore null ?


Thanks

PGI-Bis
04-05-2007, 18:28
la notazione

tipo...nome

indica un vararg. Un vararg è un parametro a lunghezza variabile. Dire

int...values

significa che il metodo può ricevere come argomento un numero variabile (da zero a n) di valori di tipo int.

E' più che altro una comodità sintattica.

Ho creato i tipi Decibel e Frequenza per una questione di significato. Quelle cose lì rappresentano decibel e frequenze. Stante il nome, è difficile che la cosa sfugga. C'è una teoria delle scienze cognitive dietro a questo essere così espliciti. Questa teoria dice che l'acquisizione di conoscenza di un fenomeno richiede meno concentrazione da parte di un essere umano se il fenomeno è costruito in modo tale da suggerire, in tutto o in parte, il proprio significato. E' chiamata memoria esterna e spiega come fa un cervello da meno di 1 gigabit a sapere tutto quello che sa. Ma questa è un'altra storia...

spillo491
05-05-2007, 11:46
Perchè valoriDecibel e valoriFrequenze sono definiti HashSet e perchè devo ordinare questi valori quando li vado a prelevare per costruirmi il pannello inserimento dati ?
Perchè hashset è un insieme non ordinato di oggetti ?

Thanks

PGI-Bis
05-05-2007, 12:06
Esatto. Ordino i valori perchè l'hashset non è ordinabile.

Uso HashSet nell'audiogramma perchè questo tipo di struttura dati ha un tempo di accesso ai suoi elementi per lo più costante.

In pratica se voglio sapere se il Decibel X esiste nell'hashset otterrò una risposta il cui tempo di esecuzione non dipende da quanti Decibel ho già inserito nella struttura dati.

Dato l'esiguo numero di elementi trattati dall'audiogramma ed il tipo di manipolazioni richieste non penso che si noterebbe la differenza tra un hashset, con accesso O(1), e una lista, con accesso O(n). Ma ci sono abitudini maturate in diversi contesti che uno trasferisce più o meno consapevolmente in ogni software che scrive.

spillo491
05-05-2007, 20:05
Ok ho capito grazie.

Non ho mai visto questa sintassi, cioè dopo il costruttore parentesi graffe e altro codice :what: . Negli appunti tu parli di campi ? Ho cercato in rete ma non ho trovato nulla


private ActionListener ascoltatoreEventiJComboBox = new ActionListener() {
public void actionPerformed(ActionEvent e) {
JComboBox box = (JComboBox)e.getSource();
ModelloCasellaDecibel modello = (ModelloCasellaDecibel)box.getModel();
Frequenza frequenza = modello.getFrequenza();
Decibel decibel = modello.getSelectedItem();
Rilevamento.Lato lato = modello.getLato();
audiogramma.setDecibel(frequenza, lato, decibel);
}
};

PGI-Bis
05-05-2007, 20:24
La forma citata è, per la parte a destra dell'uguale, la creazione di un'istanza di una classe interna [NON locale] anonima che concretizza un'interfaccia.

ActionListener è un'interfaccia.

Sai che non si può dire:

ActionListener x = new ActionListener();

Perchè un'interfaccia non è istanziabile.

Se alle parentesi tonde fari seguire quelle graffe:

ActionListener x = new ActionListener() {};

il compilatore interpreta la cosa come:

class Anonima implements ActionListener {

};
ActionListener x = new Anonima();

cioè crea una classe interna (perchè la sua dichiarazione interviene all'interno del corpo di un'altro tipo), [che sarebbe locale se la sua dichiarazione intervenisse all'interno del corpo di un metodo o di un blocco di inizializzazione] anonima (il programmatore non specifica il nome della classe dichiarata). Con questa classe, interna locale anonima, crea poi un'istanza e la assegna alla variabile desiderata.

Campo è il termine con cui, in Java, ci si riferisce alle variabili direttamente contenute nel corpo di una classe. Intendo per contenimento diretto l'intervento della dichiarazione della variabile all'interno del blocco di codice che definisce il corpo di una classe e all'esterno di qualsiasi altro blocco presente nella classe. Un blocco è la successione di enunciati racchiusi tra due parentesi graffe, incluse.

Ps

M'era sfuggito il "private" a sinistra della dichiarazione del campo "ascoltatoreEventiJComboBox". Essendo private un modificatore apponibile ai soli membri (o ai costruttori), e non potendo un membro essere locale, ecco che la classe anonima implicitamente dichiarata ed esplicitamente definita a destra dell'uguale non risulta "locale". E' semplicemente "interna anonima".

spillo491
07-05-2007, 11:05
Sto imparando un sacco di cose :D

Non mi è chiarissimo questa parte di codice nella classe Main
Prima di eseguire il metodo start quali sono gli eventi "pendenti" nel nostro caso?


// Ogni thread diverso da EventDispatcher (Thread, unico, che si occupa di gestire il mutamento di tutti i
// componenti di un'interfaccia grafica Swing) che voglia aggiornare un componente Swing deve
// trovare il modo di "infilare" la richiesta di aggiornamento nella coda di esecuzione di
// EventDispatcher. invokeLater fa esattamente questo.
// InvokeLater affida ad EventDispatcher il proprio Runnable e restituisce immediatamente il controllo al thread corrente
// Prima di eseguire il "Runnable" EventDispatcher deve consumare tutti gli eventi "pendenti"

SwingUtilities.invokeLater
(new Runnable() {
public void run() {
new Main().start();
}
}
);

PGI-Bis
07-05-2007, 11:52
Be' dipende. Supponendo che quel metodo main di quella classe Main sia il punto d'entrata di un programma Java, il fatto che prima dell'esecuzione del metodo run del Runnable passato ad invokeLater esistano degli eventi pendenti è un dettaglio di realizzazione del framework Swing/AWT.

Cioè osservando quel codice io dovrei dire che non ce ne sono e che, quindi, l'esecuzione di new Main().start() è il primo compito spettante all'EDT (Event Dispatcher Thread).

Tuttavia, esaminando le regole del framework Swing/AWT, si scopre che potrebbero già esserci eventi in consumazione, perchè le norme del framework non lo escludono.

Nel caso in cui il programma Java non parta dal metodo main di quella classe Main la preesistenza di eventi AWT nella coda degli eventi AWT è un fatto che dipende da cosa il programma abbia già fatto prima di invocare quel main.

Ciò detto, quell'arzigogolo di parentesi ha l'unico scopo di causare l'esecuzione di:

new Main().start()

equivalente a:

Main main = new Main();
main.start();

all'interno dell'EDT. Il motivo sta nel fatto che quella particolare classe Main possiede, vuoi nel costruttore, vuoi nel metodo start, vuoi negli inizializzatori, istruzioni che maneggiano componenti Swing proiettabili.

Swing è un framework a Thread singolo. Per una librerie che maneggia interfacce grafiche utente significa che esiste un solo Thread che si occupa di aggiornare l'aspetto dei componenti proiettabili sullo schermo.

L'aspetto di un componente dipende da un insieme di proprietà dell'oggetto che lo rappresenta. Swing presuppone che le mutazioni di stato dell'oggetto-componente proiettabile, siano affidate all'EDT. Lo presuppone ma non lo impone. Ciò significa che io posso cambiare il valore del colore di un componente tramite un Thread diverso dall'EDT. Qual'è il risultato? Il risultato è indeterminato. E' indeterminato per via di alcune regole del linguaggio di programmazione Java le quali trattano il caso dell'accesso in lettura o scrittura al valore di variabili residenti nella regione di memoria condivisa dai Thread (c.d. Heap).

Dunque, se, in ipotesi, cambio il colore di un componente all'interno dell'EDT io so che quella mutazione si rifletterà sul componente. Se cambio il colore all'interno di un Thread diverso dall'EDT io non posso essere certo del risultato.

La cosa vale per ogni proprietà di ogni oggetto-componente Swing. Dimensioni, componenti contenuti, font, bordi eccetera.

Quando maneggio le proprietà di un componente Swing lo devo fare all'interno dell'EDT altrimenti l'effettività (cioè il fatto che quei maneggiamenti producano l'effetto desiderato) è incerta.

spillo491
07-05-2007, 15:46
:ave: chiaro come sempre :D

Mi sai dire dove cercare materiale su FontRenderContext e TextLayout ?
Dalla documentazione java ci capisco poco
grazie

PGI-Bis
07-05-2007, 15:51
Non so cosa si trovi in rete. Di cartaceo c'è Java 2D Graphics, di J. Knudsen. Comunque è un argomento correlato a Java2D.

spillo491
07-05-2007, 18:44
Non riesco a capire i parametri del metodo draw della classe TextLayout


draw(Graphics2D g2, float x, float y)


(x,y) sono le coordinate dell'origine del textLayout cioè da documentazione
"which is the intersection of the TextLayout object's baseline with its left edge"

Cosa è la object's baseline ? In pratica è l'angolo in basso a sinistra del testo?

PGI-Bis
07-05-2007, 19:37
Hai presente la lettera g minuscola? Ecco, la baseline è la linea su cui è appoggiato "il pallino" mentre la "gambetta" si estendo sotto la baseline.

La documentazione dice che nel punto (x,y) è collocata l'intersezione tra la linea di base e il lato sinistro (guardando lo schermo) della parola. E' il punto a sinistra ma non è esattamente "in basso". E' un pelo più in su che in basso.

spillo491
07-05-2007, 19:39
Un'altra cosa scusa


public PainterAudiogramma() {
try {
pallino = ImageIO.read(getClass().getResource("/images/pallino.png"));
crocetta = ImageIO.read(getClass().getResource("/images/crocetta.png"));
} catch(java.io.IOException ex) {
throw new RuntimeException("Cannot load needed images");
}
}


Domanda stupida : come mai li definisci nel costruttore il pallino e la crocetta ?

In pratica qui leggi le immagini da due file png che avevi già tu. Cosa c'entra l'url ?

PGI-Bis
07-05-2007, 20:21
Non è che io avessi molta scelta :D. La lettura di un'immagine con ImageIO rilascia un'eccezione controllata. Per catturarla con un blocco try-catch devo per forza essere o nel corpo di un costruttore o nel corpo di un metodo o in un blocco di inizializzazione.

Non uso un metodo (alla stregua di un public void init()) perchè voglio che il campo sia certamente inizializzato prima che altri metodi di quella classe possano essere invocati.

Nel caso concreto potrei usare un blocco di inizializzazione perchè non sfrutto nessuna delle caratteristiche che distinguono i costruttori dai blocchi di inizializzazione: per abitudine opto per il costruttore.

Una nota: la certezza che pallino e crocetta abbiano il valore deciso nel costruttore prima che essi siano usati non è soddisfatta tramite il solo assegnamento nel costruttore. Occorre, in particolare, prestare attenzione a che i campi non siano usati in metodi ereditati, sovrascritti e invocati da uno dei super-costruttori. Ma questo è un altro paio di maniche.

Circa l'uso dell'URL o, meglio, per quanto riguarda l'individuazione delle immagini tramite l'uso del metodo getResource() di un oggetto di tipo Class (che è poi il findResource di un ClassLoader) basti osservare il fatto che

1. il percorso risultante è indipendente dalla piattaforma
2. il percorso risultante è indipendente dalla directory di esecuzione del processo che avvia il programma

Per il primo punto, la questione è nell'alternativa. Per individuare le immagini potrei specificare il loro percorso in termini assoluti. Per windows sarebbe una cosa tipo:

c:\cartellauno\cartelladue\programma\blabla\immagini\eccetera


Ora, se provi a incollare nella sezione Sistemi Operativi Alternativi una richiesta tipo "non mi trova il file che si trova in c:\blabla\blabla" noterai un'esorbitante quantità di merluzzate in faccia. Quei "coup de merlűss" sottolineerebbero l'atipicità di quel percorso in sistemi diversi dall'amatissima finestra.

Puoi usare cartelle in qualche modo collegate all'applicazione ma specificate in modo indipendente dalla piattaforma di esecuzione. Esistono alcune proprietà di sistema ("user.dir", "user.home" eccetera) che offrono percorsi di base nei quali infilare i dati del tuo programma. L'uso di questi percorsi rende il tuo programma indipendente dalla piattaforma ma dipendente da una procedura di installazione.

Il findResource, invece, è una mezza mano santa. Scova file che si trovino in percorsi gestiti dal (da un) ClassLoader e questo include la posizione delle classi del programma, a prescindere dal valore della proprietà "user.dir" (che è alterabile). Restituisce un URL perchè i file potrebbero essere su un disco locale o in rete o all'interno di un file jar. Può restituire file che si trovino impacchettati in un file JAR e, solitamente, è proprio questo l'obiettivo: una volta terminata, l'applicazione andrà preparata per la distribuzione e questo richiederà il suo impacchettamento in un file JAR insieme, tra l'altro, alle sue icone.

E' un piccolo gioiello, questo getClass().getResource.

spillo491
08-05-2007, 09:34
Ma il metodo getClass() restituisce quale classe ?

Ho finito di leggere i tuoi appunti molto utili e pure divertenti.
Adesso per prima cosa devo sistemare la griglia perchè inserendo nelle caselle combinate tutti i multipli di 5 questi compaiono pure nella griglia.
Poi devo mettere il 25 a metà di 20 e 30 dove la distanza tra 20 e 30 è uguale alla distanza tra 30 e 40
Devo in pratica sistemare la classe PainterAudiogramma

thebol
08-05-2007, 09:48
Ma il metodo getClass() restituisce quale classe ?

da quel che ho capito non restituisce nessuna classe, ma restituisce un url che punta all percorso passato. La base del percorso è il classpath dell'applicazione.

PGI-Bis
08-05-2007, 10:54
Il metodo getClass() restituisce un riferimento di tipo Class<X>. Questo riferimento di tipo Class<X> è la classe dell'istanza che subisce l'invocazione getClass(). Genere:

String s = new String();
Class<String> c = s.getClass();

Integer n = new Integer(10);
Class<Integer> c = n.getClass();

Pippo p = new Pippo();
Class<Pippo> c = p.getClass();

eccetera.

Ogni classe è associata al suo caricatore (ClassLoader). Il caricatore di classi è un oggetto che trova, legge traduce e carica nella jvm il codice byte contenuto nei file class.

Il metodo getResource delle istanze della classe Class<T> usa la capacità del caricatore di classi di trovare dei file.

thebol
08-05-2007, 11:06
Il metodo getClass() restituisce un riferimento di tipo Class<X>. Questo riferimento di tipo Class<X> è la classe dell'istanza che subisce l'invocazione getClass(). Genere:

String s = new String();
Class<String> c = s.getClass();

Integer n = new Integer(10);
Class<Integer> c = n.getClass();

Pippo p = new Pippo();
Class<Pippo> c = p.getClass();

eccetera.

Ogni classe è associata al suo caricatore (ClassLoader). Il caricatore di classi è un oggetto che trova, legge traduce e carica nella jvm il codice byte contenuto nei file class.

Il metodo getResource delle istanze della classe Class<T> usa la capacità del caricatore di classi di trovare dei file.

in effetti l'avevo spiegata malissimo... il getClass() serve per avere un "appiglio" per il classLoader

spillo491
08-05-2007, 11:37
Sono riuscito a eliminare i valori di deicbel non voluti dalla griglia ma ho difficoltà a spostare le etichette e le righe corrispondenti a 25 e 55 decibel !
In pratica per 25 (quindi anche 30) e 55 (quindi anche 60) ho un'altezzaEtichettaDecibel diversa e una altezzaRiga diversa. precisamente la metà

Sono riuscito a farlo per il 25 ma il codice è illeggibile e confuso


Collection<Decibel> valoriDecibelbis = Utils.creaInsiemeDecibel(
10, 20, 25, 30, 40,50, 55, 60, 70, 80, 90, 100);
for(Decibel d : valoriDecibelbis) {

String testo = String.valueOf(d);
if(d.intValue() == 25) {
testo = "Normale " + testo;
}


double yArea = origine.getY() + indiceScorrimentoDecibel * altezzaEtichetteDecibel;
if(d.intValue() == 30) {
yArea = origine.getY() + indiceScorrimentoDecibel * altezzaEtichetteDecibel-altezzaEtichetteDecibel/2;
}
if(d.intValue() == 25 || d.intValue() == 30) {
altezzaEtichetteDecibel = altezzaEtichetteDecibel/2;
}
if(d.intValue() > 30) {
yArea = origine.getY() + (indiceScorrimentoDecibel-1) * altezzaEtichetteDecibel;
}

Rectangle2D area = new Rectangle2D.Double(
xArea + MARGINE_DESTRO_ETICHETTE_DECIBEL,
yArea + MARGINE_BASSO_ETICHETTE_DECIBEL,
larghezzaEtichetteDecibel,
altezzaEtichetteDecibel);
disegnaStringaInBassoADestra(area, graphics, dati.getFontEtichette(), testo);
indiceScorrimentoDecibel++;
altezzaEtichetteDecibel = calcolaAltezzaEtichetteDecibel(
audiogramma, graphics, dati);

}


Questo è il mio problema usuale, non riesco a implementare un algoritmo per far fare quello che voglio alla JVM.
Forse disegnare prima le etichette dei multipli di 10 e poi quelle di 25 e 55 ?

PGI-Bis
08-05-2007, 12:26
La griglia dell'audiogramma è un componente di una certa complessità. Avere qualche problema nel realizzarlo non è cosa di cui stupirsi.

Puoi costruire un programma componendo le soluzioni che trovi in prototipi creati separatamente.

Prova a scrivere un'applicazione che apre una finestra dentro a cui c'è un componente nel quale è disegnata quella mini-griglia. Lo scheletro potrebbe essere:

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;

public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
buildAndShow();
}
});
}

private static void buildAndShow() {
JFrame frame = new JFrame("Grid sample");
GridPanel panel = new GridPanel();
frame.add(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
}

class GridPanel extends JComponent {
private int colWidth = 50;
private int rowHeight = 50;
private int rowCount = 5;

public Dimension getPreferredSize() {
Dimension standardSize = super.getPreferredSize();
standardSize.width = colWidth;
standardSize.height = rowCount * rowHeight;
return standardSize;
}

public void paint(Graphics graphics) {
Graphics2D g = (Graphics2D)graphics;
//pronti via:...
}
}

Troverai una soluzione per un caso speciale: quello dell'immagine che hai allegato. Una volta trovata quella soluzione speciale potrai tentare di generalizzarla. Passerai dal realizzare una griglia in cui le prime due righe sono alte H, la terza e la quarta H/2, la quinta H, ad una griglia in cui le righe possono avere altezza H o H/2. Dovrai stabilire un modo per identificare le righe che hanno altezza H e quelle che hanno altezza H/2. Poi provi ad trasportare la soluzione nel PainterAudiogramma. Se il PainterAudiogramma si dimostri "ostile" a questa mutazione lo prendi, lo butti nel cestino e ne fai uno più docile.

Calma, sangue freddo e coltello tra i denti.

spillo491
08-05-2007, 20:29
Perchè mi da errore ?


import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;

class GridPanel extends JComponent {
private int colWidth = 50;
private int rowHeight = 50;
private int rowCount = 5;
Point2D origine = new Point2D.Double(1,1);

public Dimension getPreferredSize() {
Dimension standardSize = super.getPreferredSize();
standardSize.width = colWidth;
standardSize.height = rowCount * rowHeight;
return standardSize;
}

public void paint(Graphics graphics) {
Graphics2D g = (Graphics2D)graphics;
graphics.setPaint(Color.BLACK);

Rectangle2D.Double bordoGriglia =
new Rectangle2D.Double(origine.getX(), origine.getY(),colWidth,rowHeight*rowCount);

graphics.draw(bordoGriglia);

}
}


Mi dice che non trova la classe JComponent :mbe:

PGI-Bis
08-05-2007, 20:36
Ti do un indizio. Guarda le dichiarazioni import che hai fatto. Poi guarda in che package sta JComponent.

spillo491
08-05-2007, 21:07
Giusto , devo importare javax.swing. Per usare setpaint non basta importare java.awt.* ?

PGI-Bis
08-05-2007, 21:18
La clausola

import

a meno che non sia

import static

importa le definizioni dei tipi. Classi, interfacce, enumerativi, annotazioni. Vale a dire che tu scrivi:

import java.awt.*;

non per usare "setPaint" ma per usare (tra gli altri) "Graphics". Poi le istanze di Graphics hanno un metodo setPaint ma il fatto che tu possa usare setPaint non dipende dalla clausola import.

spillo491
08-05-2007, 21:27
Ok ho capito devo usare un oggetto Graphics2D quindi dire

g.setPaint non graphics.setPAint

PGI-Bis
08-05-2007, 21:30
No. Ni. Non lo so. Prima ho scritto "per usare setPaint devi avere Graphics" ma ho sbagliato. setPaint è un metodo di Graphics2D, non di Graphics. A parte questo il resto vale. Cioè Graphics2D "ti arriva" perchè importi il package java.awt.*

spillo491
09-05-2007, 11:13
Ciao PGi sono riuscito a scrivere questo codice ed ottenere quel disegno che avevvo messo in allegato, adesso devo riuscire a generalizzarlo ? Ti sembra un buon inizio ?


import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.font.*;

public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
buildAndShow();
}
});
}

private static void buildAndShow() {
JFrame frame = new JFrame("Grid sample");
GridPanel panel = new GridPanel();
frame.add(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
}


class GridPanel extends JComponent {
private int colWidth = 50;
private int rowHeight = 50;
private int rowCount = 5;
Point2D origine = new Point2D.Double(10,10);
private int rowHeightbis = 50;
private double y = origine.getY();
private Font fontEtichette = new Font("Serif", Font.PLAIN, 12);


public Dimension getPreferredSize() {
Dimension standardSize = super.getPreferredSize();
standardSize.width = colWidth;
standardSize.height = rowCount * rowHeight;
return standardSize;
}

public void paint(Graphics graphics) {
Graphics2D g = (Graphics2D)graphics;
int [] valoriDecibel = {10, 20, 25, 30, 40};

g.setPaint(Color.BLACK);

for(int i=0; i<valoriDecibel.length; i++){

if(valoriDecibel[i] == 25||valoriDecibel[i]==30) rowHeightbis = rowHeightbis/2;
Rectangle2D.Double area = new Rectangle2D.Double(
origine.getX(),
y,
colWidth,
rowHeightbis);
g.draw(area);
disegnaStringaInBassoADestra(area, g , fontEtichette , String.valueOf(valoriDecibel[i]));
y += rowHeightbis;
rowHeightbis = 50;
}
}


private void disegnaStringaInBassoADestra(Rectangle2D area, Graphics2D graphics, Font font, String

text) {
FontRenderContext context = graphics.getFontRenderContext();
TextLayout layout = new TextLayout(text, font, context);
Rectangle2D bounds = layout.getBounds();
double y = area.getY() + bounds.getHeight() + (area.getHeight()-bounds.getHeight());
double x = area.getX() + area.getWidth() - bounds.getWidth();
graphics.setPaint(Color.BLACK);
layout.draw(graphics, (float)(x), (float)(y));
}
}

PGI-Bis
09-05-2007, 11:44
C'è un problema di "accumulo". Prova a ridimensionare la finestra. Noterai che la griglia scompare. A rallentatore si vede che schizza verso il basso.

Il metodo paint è invocato dall'API Swing più e più volte. Se usi dei campi come valori di riferimento devi fare in modo che quei campi abbiano il valore corretto a prescindere dal numero di volte per cui è invocato il metodo in cui li usi.

Nel caso di specie, il problema è che il campo "y" viene incrementato nel metodo paint. Questo valore dovrebbe essere 10 (origine.getY()) all'inizio del disegno ma invocazioni successive di paint si ritrovano ad avere un y che vale inizialmente "sempre di più".

Per correggere il problema è sufficiente trasformare la dichiarazione di origine e y da dichiarazione di campo a dichiarazione di variabile locale al metodo paint.

public void paint(Graphics graphics) {
Point2D origine = new Point2D.Double(10, 10);
double y = origine.getY();
//eccetera

Ora devi analizzare il codice di PainterAudiogramma e vedere se e come sia possibile trasferire le particolarità di disegno che hai sperimentato.

Il fatto che talune righe sono più basse di altre influisce sulla punto a partire dal quale disegni le rispettive linee. E' una cosa che certamente hai già notato perchè il codice che hai incollato verifica questa condizione mutando il valore di incremento per y.

Si può fare la stessa cosa in PainterAudiogramma?

Ricorda che il codice è materia viva, plasmabile. Soprattutto il codice Java. Ad esempio puoi prendere PainterAudiogramma e commentare le linee che vanno da 68 a 140. Ti resta in pratica:

public void paint(Audiogramma audiogramma, Graphics2D graphics, DatiPainterAudiogramma dati) {
LinkedList<Frequenza> valoriFrequenze = getFrequenzeOrdinateNonNull(audiogramma);
LinkedList<Decibel> valoriDecibel = getDecibelOrdinatiNonNull(audiogramma);

double larghezzaColonnaIntestazione = calcolaLarghezzaColonnaIntestazione(
audiogramma, graphics, dati);
double altezzaRigaIntestazione = calcolaAltezzaRigaIntestazione(
audiogramma, graphics, dati);
graphics.setPaint(Color.BLACK);
disegnaStringaAlCentro(
new Rectangle2D.Double(0, MARGINE_BASSO_ETICHETTE_INTESTAZIONE,
larghezzaColonnaIntestazione, altezzaRigaIntestazione),
graphics,
dati.getFontEtichette(),
"PERDITA IN DECIBEL");
double altezzaEtichetteDecibel = calcolaAltezzaEtichetteDecibel(
audiogramma, graphics, dati);
double larghezzaEtichetteDecibel = calcolaLarghezzaEtichetteDecibel(
audiogramma, graphics, dati);
int indiceScorrimentoDecibel = 0;
Point2D origine = new Point2D.Double(
larghezzaColonnaIntestazione / 2 + larghezzaEtichetteDecibel,
altezzaRigaIntestazione);
double xArea = origine.getX() - larghezzaEtichetteDecibel;

for(Decibel d : valoriDecibel) {

String testo = String.valueOf(d);
if(d.intValue() == 25) {
testo = "Normale " + testo;
}
double yArea = origine.getY() + indiceScorrimentoDecibel * altezzaEtichetteDecibel;
Rectangle2D area = new Rectangle2D.Double(
xArea + MARGINE_DESTRO_ETICHETTE_DECIBEL,
yArea + MARGINE_BASSO_ETICHETTE_DECIBEL,
larghezzaEtichetteDecibel,
altezzaEtichetteDecibel);
disegnaStringaInBassoADestra(area, graphics, dati.getFontEtichette(), testo);
indiceScorrimentoDecibel++;
}
/* ... commentato ... */
}

E' la parte in cui il codice disegna le etichette dei decibel. Puoi introdurre qui un controllo simile a quello che hai sperimentato?

spillo491
09-05-2007, 12:45
Si il problema della finestra l'avevo notato, ora ho risolto facendo come mi hai detto tu.

Per quanto riguarda la modifica di PainterAudiogramma dici di mantenere la parte in cui vengono disegnate le etichette e modificare solo la fase in cui disegno la griglia ?

PGI-Bis
09-05-2007, 13:07
Il disegno della griglia dipende dal disegno delle etichette. O, meglio, il disegno delle linee e delle etichette segue la stessa idea di base che, al momento, consiste nell'avere un'altezza iniziale uguale per tutte le righe.

Variando l'altezza delle righe non so quanto il codice già scritto possa essere semplicemente aggiustato.

E' più facile specializzare che generalizzare. Rispetto a quello che vuoi ottenere (cioè la possibilità che alcune righe abbiano altezza diversa dalle altre) il codice di paint è speciale (tutte le righe hanno la stessa altezza).

Io penso che il nuovo paint possa essere diviso in due parti. Nella prima calcoli l'altezza di ogni riga e la rendi accessibile, magari attraverso una struttura dati indicizzata, al resto del codice. Una cosa del genere.

Hai N righe? Crei un array di N interi. Per ogni riga di indice K calcoli la sua altezza e la infili nell'array in posizione K. Dopo aver fatto tutti i conti passi a disegnare le righe, una per volta, in un ciclo indicizzato da 0 a N. Ogni passaggio del ciclo recupera l'altezza di quella riga accedendo al valore di indice x (0 - N) nell'array delle altezze.

E' un po' sintetica come spiegazione ma spero che renda l'idea.

spillo491
09-05-2007, 13:36
Tu dici proprio una cosa del tipo ?

int[] altezzaRighe = new int[N]

Ma nel ciclo disegno contemporaneamente etichette e griglia ? no vero, faccio due cicli separati :mbe:

PGI-Bis
09-05-2007, 13:43
Fai come ti sembra più comodo. Un ciclo solo sarebbe più efficiente ma l'efficienza è una questione di cui non mi occuperei in questo momento.

spillo491
09-05-2007, 18:20
Allora ho modificato il metodo calcolaAltezzaEtichetteDecibel come segue:


private double[] calcolaAltezzaEtichetteDecibel(
Audiogramma audiogramma,
Graphics2D graphics,
DatiPainterAudiogramma dati)
{
LinkedList<Decibel> valoriDecibel = getDecibelOrdinatiNonNull(audiogramma);
double[] altezzeRighe = new double[valoriDecibel.size()];
double maxValue = dati.getMinimaAltezzaRighe();
Collection<Decibel> decibels = audiogramma.getValoriDecibel();
for(Decibel d : decibels) {
if(d == null) continue;
String testo = String.valueOf(d);
double altezza = getAreaStringa(
testo,
graphics,
dati.getFontEtichette()).getHeight();
maxValue = Math.max(altezza, maxValue);
}
for(int i=0; i<valoriDecibel.size(); i++){
if(i != 2 && i != 3 && i != 6 && i != 7) altezzeRighe[i] = maxValue;
else altezzeRighe[i] = maxValue/2;
}
return altezzeRighe;
}


e il metodo paint come segue


public void paint(Audiogramma audiogramma, Graphics2D graphics, DatiPainterAudiogramma dati) {
LinkedList<Frequenza> valoriFrequenze = getFrequenzeOrdinateNonNull(audiogramma);
LinkedList<Decibel> valoriDecibel = getDecibelOrdinatiNonNull(audiogramma);

double larghezzaColonnaIntestazione = calcolaLarghezzaColonnaIntestazione(
audiogramma, graphics, dati);
double altezzaRigaIntestazione = calcolaAltezzaRigaIntestazione(
audiogramma, graphics, dati);
graphics.setPaint(Color.BLACK);
disegnaStringaAlCentro(
new Rectangle2D.Double(0, MARGINE_BASSO_ETICHETTE_INTESTAZIONE,
larghezzaColonnaIntestazione, altezzaRigaIntestazione),
graphics,
dati.getFontEtichette(),
"PERDITA IN DECIBEL");
double[] altezzaEtichetteDecibel = calcolaAltezzaEtichetteDecibel(
audiogramma, graphics, dati);
double larghezzaEtichetteDecibel = calcolaLarghezzaEtichetteDecibel(
audiogramma, graphics, dati);
int indiceScorrimentoDecibel = 0;
Point2D origine = new Point2D.Double(
larghezzaColonnaIntestazione / 2 + larghezzaEtichetteDecibel,
altezzaRigaIntestazione);
double xArea = origine.getX() - larghezzaEtichetteDecibel;

// disegno le etichette
for(Decibel d : valoriDecibel) {

String testo = String.valueOf(d);
if(d.intValue() == 25) {
testo = "Normale " + testo;
}
double yArea = origine.getY() + indiceScorrimentoDecibel * altezzaEtichetteDecibel[i];
Rectangle2D area = new Rectangle2D.Double(
xArea + MARGINE_DESTRO_ETICHETTE_DECIBEL,
yArea + MARGINE_BASSO_ETICHETTE_DECIBEL,
larghezzaEtichetteDecibel,
altezzaEtichetteDecibel[i]);
disegnaStringaInBassoADestra(area, graphics, dati.getFontEtichette(), testo);
indiceScorrimentoDecibel++;
}



}


Il mio probelma è la i in altezzaEtichetteDecibel[i] che non so come determinare. dovrei avere la posizione del decibel x nella lista ordinata valoriDecibel

PGI-Bis
09-05-2007, 18:38
Il ciclo foreach

for(bli : bla)

è una "comodità". A volte. A volte no. Nel tuo caso è no. Per avere l'indice, puoi cambiare la linea:

for(Decibel d : decibels) {

in:

for(int indice = 0; indice < decibels.size(); indice++) {
Decibel d = decibels.get(indice);
//eccetera

spillo491
11-05-2007, 15:43
Ciao PGI purtroppo in questi giorni sarò un po preso dal lavoro e in più ieri mi è partito l'hard-disk del mio portatile :muro: era vecchio e dovrò cambiarlo:doh:

Spero di poter continuare questo programmino perchè mi ha preso parecchio

ciao