PDA

View Full Version : [JAVA] Semplice calcolo Area Rettangolo


Jim Fox
18-09-2008, 16:33
Allora, di sotto vi riporterò il codice scritto (funzionante), ma nn sono riuscito ad inserire e capire (come richiesto dal libro), dove, quando e perché inserire i metodi getWidth e getHeight.

L'esercizio mi chiedeva semplicemente questo:
"Costruire un oggetto Rectangle che ne calcoli l'area e la visualizzi. Usare i metodi getWidth e getHeight e visualizzare anche il valore previsto."


Io ho creato l'oggetto Rectangle. L'ho inserito in un frame e calcolato l'area, visualizzando il risultato della stessa.

Qualcuno sa dirmi se ho sbagliato qualcosa e soprattutto come dovevo usare in questo caso i metodi getWidth e getHeight? Voglio assolutamente capire il concetto.

Grazie mille! :p


- CLASSE RECTANGLE COMPONENT
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JComponent;

// Disegnare un rettangolo e visualizzare l'area calcolata

public class RectangleComponent extends JComponent
{
public void paintComponent(Graphics g)
{

// recupero Graphics2D
Graphics2D g2 = (Graphics2D) g;

//costruisco il rettangolo e lo disegno
Rectangle box = new Rectangle(5, 10, 40, 80);
g2.draw(box);

// calcolo l'area del rettangolo e la visualizzo
int base, altezza, area;
base = 40;
altezza = 80;
area = base * altezza;
System.out.println("Area = " + area);
}

}


- CLASSE RECTANGLEVIEWER
import javax.swing.JFrame;

public class RectangleViewer
{
public static void main(String[] args)
{
JFrame frame = new JFrame();

// imposto la grandezza del frame
frame.setSize(100, 200);

// imposto il titolo
frame.setTitle("Area Rettangolo");

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// richiamo RectangleComponent e lo aggiungo al frame
RectangleComponent component = new RectangleComponent();
frame.add(component);

// rendo visibile il frame
frame.setVisible(true);
}

}

Oceans11
18-09-2008, 16:54
"Costruire un oggetto Rectangle che ne calcoli l'area e la visualizzi. Usare i metodi getWidth e getHeight e visualizzare anche il valore previsto."


mmm...sento che mi sfugge qualcosa....!!

Ci sono sul costruire un oggetto Rectangle, per l'area basta fare il prodotto larghezza*altezza, per visualizzare il tutto basta anche una stampa a video, quindi senza finestre & co......ma per il valore previsto, proprio non mi trovo :mc:

Che vuol dire?ma è proprio quello il testo dell'esercizio?

Comunque i metodi getWidth e getHeight sono metodi accessori degli oggetti di tipo Rectangle. Questi metodi accessori, lo saprai, restituiscono i valori delle variabili di istanza dell'oggetto.

ad esempio la classe Rectangle sarà fatta più o meno:


public class Rectangle {
private int posizioneX;
private int posizioneY;
private int larghezza;
private int altezza;

public Rectangle(int x, int y, int width, int height) {
posizioneX = x;
posizioneY = y;
larghezza = width;
altezza = height;
}

public int getWidth() {
return larghezza;
}

public int getHeight() {
return altezza;
}
}


questi metodi si usano per poter tenere private le variabili di istanza, in modo che un cliente della classe possa accedere ad esse solo tramite metodi.

banryu79
18-09-2008, 17:19
Ciao Jim Fox,

credo che la richiesta di utilizzare i metodi getWidth() e getHeight() della classe Rectangle che usi nella tua classe RectangleComponent fosse relativa proprio al calcolo dell'area.

Mi spiego: tu per costruire il tuo Rectangle hai fatto così:

[...]
Rectangle box = new Rectangle(5, 10, 40, 80);
[...]


per calcolare l'area ti sei basato su delle variabili inizializzate con quelli che in gergo si chiamano "magic numbers" (ovvero valori inseriti direttamente nel codice):

[...]
int base, altezza, area;
base = 40;
altezza = 80;
area = base * altezza;
[...]


invece un metodo migliore sarebbe quello di usare i valori che sono già presenti nell'istanza appena creata di Rectangle, e per farlo basta "chiederli" direttamente all'oggetto, cosi:

int area = box.getWidth() * box.getHeight();


Puoi anche fare un confornto per vedere se così ottieni il risultato che ti aspetti:

int area1 = 80 * 40;
int area2 = box.getWidth() * box.getHeight();
System.out.println("Confronto tra area1 e area2");
System.out.println("area1 = " + area1);
System.out.println("area2 = " + area2);

Oceans11
18-09-2008, 17:23
Ciao Jim Fox,

credo che la richiesta di utilizzare i metodi getWidth() e getHeight() della classe Rectangle che usi nella tua classe RectangleComponent fosse relativa proprio al calcolo dell'area.

Mi spiego: tu per costruire il tuo Rectangle hai fatto così:

[...]
Rectangle box = new Rectangle(5, 10, 40, 80);
[...]


per calcolare l'area ti sei basato su delle variabili inizializzate con quelli che in gergo si chiamano "magic numbers" (ovvero valori inseriti direttamente nel codice):

[...]
int base, altezza, area;
base = 40;
altezza = 80;
area = base * altezza;
[...]


invece un metodo migliore sarebbe quello di usare i valori che sono già presenti nell'istanza appena creata di Rectangle, e per farlo basta "chiederli" direttamente all'oggetto, cosi:

int area = box.getWidth() * box.getHeight();


Puoi anche fare un confornto per vedere se così ottieni il risultato che ti aspetti:

int area1 = 80 * 40;
int area2 = box.getWidth() * box.getHeight();
System.out.println("Confronto tra area1 e area2");
System.out.println("area1 = " + area1);
System.out.println("area2 = " + area2);



Ah...se è così allora mi inchino!!!

Possibile che non ci sono arrivato?!?:doh:

Jim Fox
19-09-2008, 01:45
Innanzitutto grazie mille del supporto ragazzi! Visto che sono partito da zero in programmazione, ci sto mettendo il massimo impegno e con il vostro aiuto sto riuscendo a capire molte cose e soprattutto sto imparando a ragionare...

Tornando all'esercizio, ho buttato giù il programma che mi avevate suggerito, ma il compilatore (ora ho iniziato ad utilizzare un IDE, NetBeans x la precisione), mi dava sempre errore su:
int area = box.getWidth() * box.getHeight();

Ci ho messo un bel pò x capire il motivo, poi sono andato a leggermi la documentazione API per la classe Rectangle e rileggendo meglio il libro, notavo che per i metodi "getWidth, getHeight, getX e getY" viene utilizzato "double" e non int.
Infatti con il codice che seguirà, tutto funziona correttamente:

import java.awt.Rectangle;

public class RectangleComponent
{
public static void main(String[] args)
{
Rectangle box = new Rectangle(5, 10, 80, 40);

double area1 = 80 * 40;
double area2 = box.getWidth() * box.getHeight();
System.out.println("Confronto tra area1 e area2");
System.out.println("area1 = " + area1);
System.out.println("area2 = " + area2);
}
}

Mi confermate questa cosa ragazzi??? ;)

banryu79
19-09-2008, 07:47
Mi confermate questa cosa ragazzi??? ;)
Sì :)

Volendo, se è richiesto che l'area sia memorizzata in un int, ti bastava fare un cast esplicito:

int area;
[...]
area = (int) (box.getWidth() * box.getHeight());



Ci ho messo un bel pò x capire il motivo, poi sono andato a leggermi la documentazione API per la classe Rectangle e rileggendo meglio il libro...

Ottimo, questo è l'atteggiamento giusto ;)

Oceans11
19-09-2008, 08:41
per la classe Rectangle e rileggendo meglio il libro, notavo che per i metodi "getWidth, getHeight, getX e getY" viene utilizzato "double" e non int.


:eekk:


ehmmm...caspita, per davvero!

:rolleyes: una delle cose che ho sempre fatto, in automatico, ma non ho mai aperto gli occhi e non ci ho mai riflettuto sopra!
Visto? anche io sto imparando qualcosa da te. :D

A questo punto approfitto del post per chiedere:

come mai questa scelta? Ora ho controllato, sia rectangle che point che dimension vengono costruiti con int, ma poi vengono restituiti con double...e quindi la domanda è spontanea....perchè?

Jim Fox
19-09-2008, 13:53
Allora, vi riporto un atro quesito... Sotto il testo:

Scrivete un programma FourRectanglePrinter che costruisca un oggetto Rectangle, visualizzi la sua posizione invocando System.out.println(box) e quindi lo sposti e ne visualizzi la posizione per altre tre volte, in modo che, se i rettangoli fossero disegnati, formerebbero un unico grande rettangolo.

Io l'ho scritto così:

import java.awt.Rectangle;

public class FourRectanglePrinter {

public static void main(String[] args) {

// costruisco il rettangolo
Rectangle box = new Rectangle(50, 50, 60, 80);
System.out.println(box);

// sposto il rettangolo di 60 unità verso dx e lo visualizzo
box.translate(60, 0);
System.out.println(box);

// sposto il rettangolo di altre 60 unità verso dx e lo visualizzo
box.translate(120, 0);
System.out.println(box);

// sposto il rettangolo di altre 60 unità verso dx e lo visualizzo
box.translate(180, 0);
System.out.println(box);
}
}

Il risultato che compare alla compilazione è il seguente:
java.awt.Rectangle[x=50,y=50,width=60,height=80]
java.awt.Rectangle[x=110,y=50,width=60,height=80]
java.awt.Rectangle[x=230,y=50,width=60,height=80]
java.awt.Rectangle[x=410,y=50,width=60,height=80]


Che ne pensate? Il regionamento è giusto o x caso mi chiedeva di visualizzare i 4 rettangoli disegnati?

Oceans11
19-09-2008, 13:59
una cosa del genere mi ricordo di averla fatta anch'io tempo fa...:D

tanto per, perchè non provi a fare tutte le stampe in un ciclo for? potrebbe esserti di esercizio. E poi prova anche a fare delle traslazioni sull'asse Y. tipo tipo così: (le O sono i rettangoli)

OO
OO

viene fuori comunque un rettangolo più grande no?

Jim Fox
19-09-2008, 14:15
Bè cicli for x il momento meglio che li lascio da parte, nn vorrei addentrarmi in cose che nn ho ancora fatto e creare confusione :D

Cmq sotto l'esercizio ci sono disegnati proprio 4 rettangolini, uniti in modo da formarne solo uno, esattamente come hai fatto tu:
OO
OO

Ora che mi hai detto: "prova anche a fare delle traslazioni sull'asse Y" ho capito di aver commesso un errore, perché il testo dell'esercizio diceva proprio di visualizzarli in quel modo :p .
Infatti così come ho fatto io viene fuori una cosa del genere: OOOO ... Sbaglio???

Oceans11
19-09-2008, 14:19
No no hai ragione.
Beh io mi ricordavo di una cosa simile ecco perchè te l'ho detto...ma stai facendo gli esercizi di programmazione sul libro di horstmann???mi sembra di averlo letto lì questo qua.

Beh per il ciclo for allora è meglio aspettare (se non vado errato e se è quello il libro, tu sei al cap.2, i cicli sono al 5 o al 6)

Jim Fox
19-09-2008, 14:29
No no hai ragione.
Beh io mi ricordavo di una cosa simile ecco perchè te l'ho detto...ma stai facendo gli esercizi di programmazione sul libro di horstmann???mi sembra di averlo letto lì questo qua.

Beh per il ciclo for allora è meglio aspettare (se non vado errato e se è quello il libro, tu sei al cap.2, i cicli sono al 5 o al 6)
Si, proprio quel libro :D ... Concetti di informatica e fondamenti di Java :p

Un ultima cosa su questo quesito voglio chiederti. Se invece di stamparli in console, io volessi visualizzare i quattro rettangolini:
OO
OO
come dovrei fare?

banryu79
19-09-2008, 14:34
Un ultima cosa su questo quesito voglio chiederti. Se invece di stamparli in console, io volessi visualizzare i quattro rettangolini:
OO
OO
come dovrei fare?
Intendi visualizzare a video mediante grafica? Allora ti toccherebbe tuffarti nelle meraviglie di Java2D e fare un minimo di conoscenza con il signor AWT e la signorina SWING.

Oceans11
19-09-2008, 14:34
Per visualizzarli dovresti fare come hai fatto all'inizio con il metodo draw(Rectangle r) di Graphics.

La classe Rectangle di java.awt è pensata solo per astrarre il concetto di forma geometrica e si è scelto di non mischiare questa definizione con il disegno!

In pratica Rectangle è un oggetto che tiene in memoria solo quello che tu vedi: coordinate (x,y) dell'angolo in alto a sinistra, larghezza e altezza. Niente più.



PS: e ci risiamo....post praticamente contemporanei ma io arrivo sempre dopo :(

Jim Fox
19-09-2008, 14:48
Appunto. Ve lo chiedevo perché già in un precedente esercizio mi era capitato di importare:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JComponent;

Era l'esercizio dove dovevo visualizzare un rettangolo in un frame ed ho dovuto creare due classi, una RectangleComponent e l'altra Rectangle Viewer.

Questo è il codice della classe RectangleComponent
public class RectangleComponent extends JComponent
{
public void paintComponent(Graphics g)
{

// recupera Graphics2D
Graphics2D g2 = (Graphics2D) g;

// costruisce un rettangolo e lo disegna
Rectangle box = new Rectangle(30, 40, 60, 80);
g2.draw(box);

// sposta il rettangolo di 15 unità verso destra e
// di 25 unità verso il basso
box.translate(35, 45);

// disegna il rettangolo nella nuova posizione
g2.draw(box);
}
}

Ora, quello che voglio chiedervi (per cercare di capire definitivamente questa storia :D ), devo per forza creare una classe x farla visualizzare in un frame oppure è possibile modificare il codice che vi ho postato sopra e far visualizzare il rettangolo li stesso?

ps: prendete in esame questo esempio del singolo rettangolo translato, poi una volta che ho capito del tutto questa cosa, voglio provare da solo a far visualizzare i 4 rettangolini. :p
OO
OO

Grazie mille ragazzi!!!!!!!!!!

Oceans11
19-09-2008, 14:53
adesso sei tu che stai correndo...:D

in sostanza per disegnare su un componente, devi creare una classe dove estendi JComponent e poi fai override di paintComponent(Graphics g), proprio come hai fatto tu. In mezzo però c'è molta teoria, che và dall'ereditarietà alla grafica con swing e awt!

banryu79
19-09-2008, 15:06
Se vuoi addentrarti in maniera graduale e guidata nelle funzionalità che Java mette a disposizione per fare rendering a video, allora ti consiglio un approccio più calmo, ragionato e completo.

Potresti partire da qui (http://java.sun.com/docs/books/tutorial/2d/index.html).

Jim Fox
19-09-2008, 15:14
adesso sei tu che stai correndo...:D

in sostanza per disegnare su un componente, devi creare una classe dove estendi JComponent e poi fai override di paintComponent(Graphics g), proprio come hai fatto tu. In mezzo però c'è molta teoria, che và dall'ereditarietà alla grafica con swing e awt!
ehehehe

Bè, il libro mi ha spiegato sommariamente queste cose, per questo nn riesco, ancora, a capire bene il meccanismo. :(

Il problema che ho avuto quando ho compilato la prima volta quel codice, è che l'IDE mi diceva che non trovava il main. Successivamente ho capito che dovevo creare all'interno del progetto una seconda classe, RectangleViewer, che mi richiamava l'altra:

import javax.swing.JFrame;

public class RectangleViewer
{
public static void main(String[] args)
{
JFrame frame = new JFrame();

frame.setSize(400, 500);
frame.setTitle("Two rectangles");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

RectangleComponent component = new RectangleComponent();
frame.add(component);

frame.setVisible(true);
}
}

In questo modo riuscivo a far visualizzare il rettangolo su un frame e senza alcun errore.

Quello che Vi chiedevo, è se posso far visualizzare il rettangolo anche "senza" un frame ed inserire il main nella prima classe RectangleComponent :stordita:

Oceans11
19-09-2008, 15:19
Non hai letto con attenzione...la risposta è no!

Per disegnare su un pannello devi (e dico devi) fare override di paintComponent (e lo fai solo estendendo la classe JComponent).

E' ancora troppo complicato, tieni in sospeso per ora!:D

Jim Fox
19-09-2008, 15:25
Non hai letto con attenzione...la risposta è no!

Per disegnare su un pannello devi (e dico devi) fare override di paintComponent (e lo fai solo estendendo la classe JComponent).

E' ancora troppo complicato, tieni in sospeso per ora!:D
Si appunto!!! Parecchio complimento x il momento :doh:

:D

Jim Fox
19-09-2008, 16:10
Naviganto in rete ho trovato la soluzione al programma che vi avevo inizialmente proposto:

import java.applet.*;
import java.awt.*;

public class FourRectanglePrinter extends Applet
{
public static Rectangle box;

public void init()
{
box = new Rectangle(20,20,40,40);
System.out.println(box);
box.translate(40,0);
System.out.println(box);
box.translate(0,40);
System.out.println(box);
box.translate(-40,0);
System.out.println(box);
}
public void paint(Graphics g)
{
g.drawRect((int)box.x,(int)box.y,(int)box.getWidth(),(int)box.getHeight());
g.drawRect((int)box.x +40,(int)box.y,(int)box.getWidth(),(int)box.getHeight());
g.drawRect((int)box.x +40,(int)box.y +40,(int)box.getWidth(),(int)box.getHeight());
g.drawRect((int)box.x,(int)box.y +40,(int)box.getWidth(),(int)box.getHeight());
}
}

Se compilate il codice in un IDE escono fuori su un'applet i 4 rettangolini uniti, come richiesto dall'esercizio.

Ora per voglio capire per bene la logica:
- estende la classe Applet (OK)

- public static Rectangle box; (PERCHE'?)

- public void init() (PERCHE'? - sulla documentazione ho trovato scritto questo: The init() method is used only for applets (as far as I know). It is called by the JVM to init the applet on client side (browser). It's a kind-of main method for applets.. Quindi è utilizzato proprio nelle applicazione applet???)

- box = new Rectangle(20,20,40,40);
System.out.println(box);
box.translate(40,0);
System.out.println(box);
box.translate(0,40);
System.out.println(box);
box.translate(-40,0);
System.out.println(box); (OK! COSTRUISCE IL RETTANGOLO E LO TRASLA)

- public void paint(Graphics g) (OK! invoca paint(Graphics g))

- g.drawRect((int)box.x,(int)box.y,(int)box.getWidth(),(int)box.getHeight());
g.drawRect((int)box.x +40,(int)box.y,(int)box.getWidth(),(int)box.getHeight());
g.drawRect((int)box.x +40,(int)box.y +40,(int)box.getWidth(),(int)box.getHeight());
g.drawRect((int)box.x,(int)box.y +40,(int)box.getWidth(),(int)box.getHeight()); (DISEGNO I RETTANGOLI)


Cmq ottimi i tutorial di SUN ;)

Oceans11
19-09-2008, 16:35
Sì le applet sono una cosa un pò particolare: non hanno main ma sovrascrivono alcuni metodi per il loro funzionamento (init() e paint() sono 2 esempi).

In particolare init() si può considerare il "main" per le applet: è lì che incomincia l'esecuzione del codice dell'applet da parte del browser o viewer.

Per la grafica in applicazioni stand-alone invece, ti sconsiglio caldamente di sovrascrivere il metodo paint, piuttosto paintComponent!

Jim Fox
19-09-2008, 17:34
Sì le applet sono una cosa un pò particolare: non hanno main ma sovrascrivono alcuni metodi per il loro funzionamento (init() e paint() sono 2 esempi).

In particolare init() si può considerare il "main" per le applet: è lì che incomincia l'esecuzione del codice dell'applet da parte del browser o viewer.

Per la grafica in applicazioni stand-alone invece, ti sconsiglio caldamente di sovrascrivere il metodo paint, piuttosto paintComponent!
Grazie ancora della disponibilità Oceans. ;)

Un ultima cosa. Mi spieghi concettualmente che significa:
public static Rectangle box;

Oceans11
19-09-2008, 17:53
quella è una variabile statica pubblica:

public sta per indicare il modificatore di accesso: in pratica a quella variabile puoi accedere anche dall'esterno della classe (e del package e anche da una classe che non estende direttamente quella in cui è dichiarata)

static significa che ce n'è una sola. Mi spiego meglio. Immagina di avere una classe, e questa classe (come quasi tutte del resto) sta lì pronta a sfornate oggetti del suo tipo. Ora immagina che come vuoi che ogni oggetto abbia le sue caratteristiche o proprietà (insomma che ogni oggetto abbia le sue variabili "d'istanza"), potrebbe capitare che vuoi anche che esista UNA SOLA variabile diciamo "in comune" a tutti gli oggetti che hai creato/devi creare.

PS: visto che scrivo con i piedi....aggiungo: "vai avanti a studiare e vedrai che il libro lo spiega moooolto meglio di quanto non faccia io" :D

Jim Fox
19-09-2008, 18:20
Infatti sai cos'è, io mi sto interstardendo con gli esercizi proposti a fine del capitolo e per questo motivo nn vado avanti... Ce ne sono alcuni dove mi fa fare cose che ancora nn ho trattato.
Visto che mi dice sempre di andare a consultare la documentazione API, penso sia un modo x farmi prendere domistichezza con questa.

Oceans11
19-09-2008, 18:29
Guarda, io penso che per quanto riguarda i primi capitoli, almeno fino al 6 quindi, gli esercizi non sono certo soddisfacenti. Voglio dire che dato che molti argomenti non sono proprio ancora affrontati, fare un programma "decente" è praticamente impossibile. Ecco perchè si chiamano esercizi! :D

Quindi io dico, non avere fretta, studia bene capitolo per capitolo e non andare avanti se non hai capito bene, e allo stesso tempo, non pretendere troppo dai tuoi esercizi, fanno quello che devono e possono!!!:)

banryu79
22-09-2008, 08:22
Visto che mi dice sempre di andare a consultare la documentazione API, penso sia un modo x farmi prendere domistichezza con questa.

Non conosco il libro in questione, sicuramente però prendere familiarità con i javadoc del JDK e imparare a consultarli con rapidità e precisione è fondamentale per uno sviluppatore Java.
Senza contare che "navigandoci" i mezzo a poco a poco si imparano a conoscere i package e quello che contengono, cioè come è strutturata la API.