Sunteți pe pagina 1din 238

Java 2 Networking and Databases

Cuprins
Modulul 1: Swing notiuni de baza si componente

1.1 NetBeans, notiuni de baza despre swing si instantierea clasei JFrame


1.2 Mostenirea clasei JFrame, folosirea butoanelor si instantierea clasei JButton
1.3 Layout Managers si aplicarea FlowLayout pe containere
1.4 JPanel si BorderLayout
1.5 JLabel si GridLayout
1.6 Fereastre interioare - JInternalFrame si clasa Cursor
1.7 Butoane de selectie si grupuri de butoane
1.8 Butoane de selectie
1.9 Clasa JComboBox
1.10 Clasa JTable
1.11 Componente text
1.12 Etichete - clasa JLabel

Modulul 2: Swing evenimente

2.1 Componente text: clasa JTextField


2.2 Componente text: clasa JTextArea
2.3 Componente text: clasa JPasswordFiled
2.4 Meniuri
2.5 Clasa JMenuItem si alte evenimente care pot fi aplicate
1

2.6 Modificari ce pot fi aduse componentelor JMenuItem


2.7 Elemente de meniu selectabile
2.8 Selectarea fisierelor cu interfata grafica - JFileChooser
2.9 WindowListener si WindowEvent
2.10 Paleta de culori
2.11 Fereastra de selectare din sistemul de fisiere

Modulul 3: MySQL Notiuni de baza

3.1 Instalarea serverului MySQ


3.2 Entitati
3.3 Baze de date
3.4 Relatii one-to-one
3.5 Relatii one-to-many
3.6 Relatii many-to-many
3.7 Dezvoltarea eficienta a entitatilor
3.8 Erori in design-ul bazei de date

Modulul 4: MySQL Interogari

4.1 Tabele, relatii si chei primare


4.2 Crearea unei tabele in aplicatia phpMyAdmin
4.3 Adaugarea unei noi inregistrari in tabela
4.4 Vizualizarea inregistrarilor din tabele
4.5 Conditionarea selectarii informatiilor din tabele dupa atribute
2

4.6 Modificarea informatiilor stocate intr-o tabela


4.7 Stergerea informatiilor din tabele

Modulul 5: Java si conexiunea la baza de date

5.1 Intelegerea legaturii dintre Java si baze de date


5.2 Crearea conexiunii cu serverul
5.3 Preluarea informatiilor din baza de date
5.4 Referinta la coloane prin numele lor
5.5 Introducerea informatiilor in baza de date
5.6 Modificarea si stergerea informatiilor
5.7 Trimiterea grupurilor de interogari
5.8 Crearea unei interfete grafice pentru afisare si stergere
5.9 Crearea unei interfete grafice pentru adaugare sau modificare

Exercitii recapitulative pentru examen

Modulul 7: Notiuni despre retele

7.1 Introducerea datelor in tabela prin interfata grafica


7.2 Crearea conexiunii la aruncarea evenimentului
7.3 Preluarea informatiilor din tabela
7.4 Crearea obiectelor raportat la entitatile bazei de date
7.5 Parcurgerea colectiei si efectuarea algoritmului

Modulul 8: Pachetul java.net

8.1 Stergerea inregistrarilor din tabela


8.2 Modificarea inregistrarilor din tabela
8.3 Tratarea evenimantului si modificarea propriu-zisa
8.4 Tratarea exceptiilor
8.5 Conexiunea cu mai multi clienti
8.6 Interfete grafice

Modulul 9: Transferul instantelor

9.1 Intelegerea retelelor


9.2 Dezvoltarea unui exemplu de aplicatie server
9.3 Dezvoltarea unui exemplu de aplicatie client
9.4 Testarea aplicatiilor

Modulul 10: Folosirea pachetului javax.mail

10.1 Functionalitatea serverului de email


10.2 Trimiterea unui mail cu Java
10.3 Trimiterea unui mail formatat HTML
10.4 Atasamente
10.5 Receptionare mesaje email cu POP3

Modulul 1: Swing notiuni de baza si componente

1.1

NetBeans, notiuni de baza despre swing si instantierea clasei


JFrame

Majoritatea aplicatiilor astazi folosesc o interfata grafica, ce are importantul rol de comunicare intre
utilizator si computer. Diferenta intre lucrul cu o consola penru folosirea unei aplicatii software si o
interfata grafica este aceea ca interfata grafica interactioneaza in mod direct cu utilizatorul si creeaza
astfel un mediu user-friendly. Orice aplicatie software ce are ca destinatie finala un utilizator
oarecare ( fara experienta in domeniu IT ) trebuie sa foloseasca obligatoriu o interfata grafica (GUI
Graphic User Interface) deoarece aceasta este mult mai usor de invatat chiar si pentru cineva care nu
a avut tangente cu programul respectiv.
Exista mai multe metode de dezvoltare a interfetelor grafice cu Java. Ne amintim de modalitatile de
creare de appleturi folosind pachetul java.awt si de metodele de dezvoltare a aplicatiilor stand-alone
cu pachetul java.swing; Swing este tehnologia pe care o vom folosi in continuare pentru dezvoltarea
tuturor aplicatiilor la cursul de Java 2 Advanced, de aceea vom face un studiu aprofundat in
primele doua module ale cursului pentru a intelege pe deplin toate componentele pe care le vom
folosi in vederea dezvoltarii aplicatiilor cu baze de date sau cu comunicare la nivelul unei retele.
Laboratoarele la acest curs le vom dezvolta in mediul de programare NetBeans. Puteti descarca
aplicatia gratuit de pe siteul official NetBeans www.netbeans.org ;
Pentru inceput sa ne amintim modul de creare a unei ferestre folosind tehnologia swing. Clasa
JFrame este cea care descrie un obiect de tip fereastra. O fereastra este de asemenea un container,
ceea ce inseamna ca poate sustine alte componente. Fereastra este princialul obiect de tip container
folosit pentru crearea unei interfete grafice pentru o aplicatie software.
Putem observa caracteristica de container a unei ferestre din ierarhia de mostenire a claselor:

java.lang.Object
java.awt.Component
java.awt.Container
java.awt.Window
java.awt.Frame
javax.swing.JFrame

Clasa JFrame are urmatorii constructori pe care ii vom folosi:

JFrame()
JFrame(String s)

Cel mai des vom folosi al doilea constructor pentru crearea instanelor de ferestre.
5

Metodele importante ce definesc comportamentul obiectului de tip fereastra sunt urmatoarele:

setIconImage(Image i)
setLayout(LayoutManager lm)
setJMenuBar(JMenuBar mb)

De asemenea foarte importanta este metoda add(Component c) parte a comportamentului oricarui


container, pe care o vom folosi pentru adaugarea de component pe fereastra.

Pentru inceput sa vedem modul de dezvoltare a unei aplicatii care sa deschida o fereastra de tip
JFrame:

Dupa deschiderea aplicatiei NetBeans va trebui sa continuam cu deschiderea unui nou proiect pentru
a creea aplicatia ceruta. Pentru a crea un proiect nou trebuie fie sa apasam optiunea New Project din
meniul File, fie sa folosim scurtatura din taste Ctrl Shift N. Imaginile de mai jos va arata modul
de creare a unui proiect nou cu NetBeans.

Selectam mai departe tipul de proiect care este Java Application;

Dupa acest pas trebuie sa denumim proiectul. Numele folosit de mine a fost Aplicatie1;

Dupa deschiderea ferestrei de editare a clasei principale a programului Main, scrisa in fisierul
Main.java, ce contine si metoda main(), se poate continua cu scrierea aplicatiei.

Fara a creea un alt fisier, am scris o aplicatie care deschide o fereastra la pornirea acesteia.
Pentru inceput fereastra apare fara o dimensiune in coltul din stanga sus al ecranului. Pentru a ii seta
acesteia o dimensiune si o pozitie default de deschidere putem folosi fie metoda setBounds(): definita
astfel:

public void setBounds(int x,int y, int width, int height);

fie separate metodele setSize() si setLocation(), definite in urmatorul mod:

setSize(int width, int height);


setLocation(int x,int y);

10

1.2

Mostenirea clasei JFrame, folosirea butoanelor si instantierea


clasei JButton

Totusi, pana in prezent nu am reusit decat crearea unei ferestre prin instantierea clasei JFrame.
Desigur, pe aceasta instanta de fereastra am putea foarte usor sa adaugam alte componente, cum ar fi
butoane, campuri de text sau etichete pentru afisare, totusi modalitatea de dezvoltare a unei aplicatii
software profesionale nu este aceasta.

In continuare vom dezvolta o clasa care instantiaza obiecte de tip fereastra ce au dj aplicate pe
acestea un buton. Practic, acesta este modul in care se dezvolta ferestre utile in asamblarea unui
program. Vom denumi aceasta clasa: FereastraPrincipala; Pentru a crea o clasa noua in cadrul
aplicatiei noastre in NetBeans mai intai vom da click dreapta pe aplicatie1, din interiorul proiectului
dezvoltat de noi. Acesta este folderol de contine fisierul Main.java; Pe meniul pop-up deschis dupa
click dreapta din optiunea New vom allege Java Class;

11

Dupa denumirea noului fisier FereastraPrincipala putem modifica continutul acestuia in editorul de
text care s-a deschis in partea dreapta.
Aici vom importa pachetul javax.swing imediat dupa apelul instructiunii package:

12

import javax.swing.*;

Este necesar pentru inceput sa mostenim clasa JFrame; pentru acest lucru folosim keyword-ul
extends, asa cum dj stim. Definitia clasei devine:

public class FereastraPrincipala extends JFrame{


}

In interioarul acoladelor va trebui sa scriem componentele clasei: Atributele,


Constructorul/Constructorii si Comportamentul obiectului FereastraPrincipala ce urmeaza sa il
definim.

Singurul atribut al obiectului de tip FereastraPrincipala in acest caz este un obiect de tip buton;

public JButton b = new JButton("Maimutzica");

Dupa cum ne amintim obiectul de tip buton este definit in clasa JButton. Cu acesta clasa putem
defini butoane cu text sau cu imagine. Pentru inceput vom folosi constructorul pentru definirea unui
buton cu text;

13

Constructorii clasei JButton sunt:

public
public
public
public

JButton ();
JButton(String text);
JButton(Icon ico);
JButton(String text, Icon ico);

Constructorul definit va arata astfel:


public FereastraPrincipala(String titlu){
super(titlu);
getContentPane().add(b);
}
Dupa cum se poate observa constructorul primeste un paramentru de tip String. Acest parametru
reprezinta titlul ferestrei, mai prcis textul care urmeaza sa apara pe bara de titlu la deschiderea
ferestrei, sau altfel, va avea acelas rol cu argumentul primit de constructorul JFrame(String titlu);

Vom trimite paramentrul catre constructorul clasei pe care o mostenim cu ajutorul metodei super(),
ce trebuie neaparat apelata ca prima linie a cosntructorului pe care il descriem;
Mai departe adaugam pe fereastra butonul cu sintaxa getContentPane().add(b);
In acest moment putem spune am am terminat construirea clasei FereastraPrincipala;
Revenim la clasa Main unde cream o instant a obiectului FereastraPrincipala si il pozitionam pe
ecran.

14

Daca dorim ca butonul nostru sa fie reprezentat si de o imagine pe langa text va trebui sa folosim
constructorul:

public JButton(String text, Icon ico);

Vom face cateva modificari in clasa FereastraPrincipala; Atrubutele clasei vor deveni:
public Icon imi = new ImageIcon("animal.jpg");
public JButton b = new JButton("Maimutzica",imi);
Imaginea animal.jpg am adaugat-o in directorul din proiect in care se afla si fisierele sursa si in cel
in care se afla clasele compilate (fisierele cu extensia .class).

Iata si rezultatul obtinut la executia programului care deschide o fereastra pe care se afla un buton cu
imaginea aleasa de mine "animal.jpg".

15

In continuare vom modifica textul de pe buton (label-ul butonului) la apasarea acestuia. Desigur
exemplul este unul clasic de folosire a evenimentului de tip ActionEvent si va ajuta sa intelegeti sau
sa va amintiti modul in care comandam executia unei instructiuni la apasarea unui buton.
Pentru inceput este necesar sa importam pachetul java.awt.event;
import java.awt.event.*;

16

Dupa importarea pachetului trebuie suprascrisa metoda actionPerformed(ActionEvent ev). Acest


lucru se poate face in acelas timp cu atasarea unui ascultator butonului de pe fereastra. In interiorul
acestei metode vom modifica label-ul butonului din "maimutzica" in "gorila".
Metoda actionPerformed(ActionEvent ev) va fi apelata la apasarea butonului, atunci cand se va
trimite un eveniment de tip ActionEvent.

17

Iata rezultatul aplicatiei:

18

1.3

Layout Managers si aplicarea FlowLayout pe containere

Pentru inceput vom crea un proiect nou. Pe acest proiect eu l-am denumit Aplicatie2. Dupa
deschiderea editorului pentru fisierul Main.java putem incepe scrierea programului prin dezvoltarea
clasei Main. Vor trebui importate pachetele javax.swing si java.awt.
import java.awt.*;
import javax.swing.*;

In interiorul clasei vom defini global o instanta a unui obiect de tip JFrame cat si o instanta de obiect
de tip JButton. Fereastra creata va fi componenta container pe care vom experimenta aplicarea
managerilor de pozitionare (Layout Managers) iar butonul va fi componenta pozitionata in container.
Asa cum va fi pozitionat in aceste exemple butonul in fereastra, similar este efectul si pentru orice
alta compoenta grafica (Eticheta, camp de text sau un alt container) la pozitionarea pe un anumit tip
de container(fereastra, panou sau applet).
Dupa instantierea celor doua clase (JFrame si JButton) in interiorul metodei main() adaugam butonul
pe interfata ferestrei. Atentie la modul de definire global a celor doua instante de obiecte. Este
necesar si obligatoriu sa folosim modificatorul "static", deoarece urmeaza sa folosim cele doua
instante in interiorul metodei main() care este prin definitie statica. Ne amintim ca o metoda statica
nu poate apela si folosi decat alte metode sau variabile statice.

19

Urmeaza sa setam un mod in care butonul va fi pozitionat pe fereastra. Default, managerul de


pozitionare pe containerele swing este BorderLayout, constanta CENTER. Dorim sa modificam
managerul de pozitionare in FlowLayout. Pentru aceasta vom folosi metoda setLayout() care
primeste ca parametru un tip de LayoutManger. Prin urmare pentru a seta FlowLayout pe fereastra
creata de noi anterior vom folosi sintaxa:
f.setLayout(new FlowLayout());
Acest mod de setare este echivalent cu:
FlowLayout flay = new FlowLayout();
f.setLayout(flay);
Pentru a vedea mai usor modificarile survenite pe interfata grafica a aplicatiei pe care o dezvoltam
vom seta o dimentsiune pentru fereastra folosind metoda setSize(), iar mai apoi vom face vizibila
aceasta fereastra cu setVisible();

20

Managerul de pozitionare FlowLayout ordoneaza componentele in sir aliniate in functie de o


constanta definita in clasa FlowLayout. Componentele pot fi orientate:

la stanga: FlowLayout.LEFT
la dreapta: FlowLayout.RIGHT
pe centru: FlowLayout.CENTER
justify spre stanga: FlowLayout.LEADING
justify spre dreapta: FlowLayout.TRAILING

Default este stata constanta CENTER, prin urmare ne asteptam ca butonul sa fie asezat pe primul
rand pe centru adica in partea de sus a ferestrei, pozitionat central.

21

Modul in care sunt ordonate componetele poate fi precizat inca de la instantierea obiectului
FlowLayout, deoarece unul dintre constructori primeste ca parametru constanta de pozitionare. In
cazul in care nu am instantiat obiectul de la inceput cu constanta dorita putem folosi mutatorul
setAlignment(int aling) pentru setarea ulterioara a modului in care dorim sa fie pozitionate
componentele pe container. Aceasta metoda primeste ca paramentru una dintre constantele
prezentate mai sus. In exemplul urmator eu am folosit direct constructorul pentru definirea modului
de aliniere al butonului:

22

Ne asteptam dupa scrierea acestui cod ca butonul sa fie pozitionat pe primul rand in partea stanga,
adica in coltul din stanga sus al ferestrei:

Desigur daca dorim alinierea la drepta a componentei vom folosi constanta RIGHT:

23

In acest moment ar trebui ca butonul sa apara in coltul din dreapta sus:

24

Pentru a vedea efectul constantelor LEADING si TRAILING vom mai adauga doua butoane pe
fereastra:

25

Efectul constantei LEADING este de ordonare justify la stanga a componentelor:

Iar efectul constantei TRAILING este de a ordona componentele justify la dreapta:

26

Observam ca in functie de marime ferestrei componentele sunt asezate pe mai multe randuri sau nu.
In imaginea de mai jos am incercat redimensionarea cu mouse-ul a ferestrei astfel incat am ajuns cu
fiecare buton pe un rand:

Spatiul care se afla intre randuri si cel dintre componente poarta denumirea de "gap" (en. crapatura).
Distanta dintre componentele de pe un rand are denumirea de "horizontal gap" iar cea dintre
randurile de componente de "vertical gap". Default aceasta distanta este de 5 pixeli, dar ea poate fi
modificata in doua moduri. Unul dintre constructorii FlowLayout permite setarea acestor distante.
Acest constructor are urmatoare definitie:

FlowLayout(int align, int hgap, int vgap)

De asemenea exista mutatorii setHgap(int gap) si setVgap(int gap) ce primesc ca paremetrii


distantele in pixeli. Mutatorul setHgap(int gap) seteaza distanta dintre componente in timp de
setVgap(int gap) seteaza distanta dintre randuri. Am exemplificat in urmatoarele imagini modul de
folosirea al acestor doi mutatori:

27

28

In exemplul urmator vom dezvolta o clasa care mosteneste JFrame. Pe aceasta vom seta default
managerul de pozitionare FlowLayout.

In clasa fereastra butonul devine unul dintre atributele clasei. Adaugarea butonului pe fereastra se
face in interiorul constructorului, deoarece acesta face parte din fiecare instanta creata a obiectului
fereastra. Sintaxa de adaugare a componentei este:

getContentPane().add(b);

Si managerul de pozitionare se seteaza tot in interiorul constructorului. Sintaxa este:

getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT));

29

Dupa salvarea clasei Fereastra in clasa main construim global o instanta de Fereastra pe care o setam
vizibila si ii dam o marima default.

30

Iata rezultatul:

31

1.4

JPanel si BorderLayout

JPanel este o componenta de tip container ce ne ajuta in principal la pozitionarea altor componente
pe ferestre, deci la crearea interferelor grafice. Un panou nu este vizibil - by default - si nici nu a fost
construit pentru a il face vizibil. Pentru inceput, pentru a putea vedea pozitionarea unei astfel de
componente vom colora fundalul panoului.
In urmatoarea aplicatie vom pozitiona un panou intr-o fereastra. Panoul va fi plasat default adica de
un manager BorderLayout.CENTER, iar pe panou vom plasa un buton in partea dreapta folosind
LayoutManager-ul FlowLayout();
Voi construi pentru inceput un nou proiect - Aplicatie3; In metoda main(), dupa importarea
pachetelor necesare voi construi o instanta de JFrame, o instanta de JPanel si o instanta de JButton.
Cele trei for fi definite global, dar toate fiind neaparat precedate de modificatorul "static";
public static JFrame f = new JFrame("Fereastra");
public static JPanel p = new JPanel();
public static JButton b = new JButton("Buton");
In interiorul metodei main(), voi adauga panoul pe fereastra folosind metoda add() specifica
containerelor:
f.add(p);
Tot cu ajutorul metodei add() voi adauga butonul pe panou. Exista doua metode de a seta un manager
de pozitionare pe un panou. Fie folosind deja cunoscuta metoda setLayout(), fie dand o instanta a
managerului ca paramentru constructorului JPanel. In aceasta aplicatie am ales sa modific
instantierea obiectului JPanel in:
JPanel p = new JPanel(new FlowLayout(FlowLayout.RIGHT));

32

33

In acest moment, datorita amplasarii default a panoului pe fereastra (BorderLayout.CENTER) panoul


ocupa exact suprafata ferestrei, iar butonul este amplasat pe primul rand in partea dreapta a acestuia,
pozitionarea componentei JButton fiind data de managerul FlowLayout setat prin intermediul
constructorului la initializarea panoului.
Vom incerca amplasarea panoului in partea de jos a ferestrei. Putem face acest lucru cu ajutorul
managerului BorderLayout.
Iata cum functioneaza LayoutManager-ul BorderLayout:
Acesta pozitioneaza componentele in functie de marginea containerului in care sunt amplasate. Acest
lucru se realizeaza prin intermediul a cinci constante specifice clasei:

BorderLayout.NORTH (pozitioneaza componenta in partea de sus a containerului)


BorderLayout.SOUTH (pozitioneaza componenta in partea de jos a containerului)
BorderLayout.EAST (pozitioneaza componenta in partea dreapta a containerului)
BorderLayout.WEST (pozitioneaza componenta in partea stanga a containerului)
BorderLayout.CENTER (pozitioneza componenta pe centrul containerului)

Sa incercam cateva exemple cu fiecare constanta aplicata panoului creat. Pentru a vedea mai usor
pozitionarea acestuia vom colora fundalul panoului in rosu. Acest lucru se face cu ajutorul metodei
setBackground(Color c) - sintaxa folosita pentru colorarea fundalului panoului fiind:
p.setBackground(Color.red)

34

35

1.5

JLabel si GridLayout

Managerul GridLayout pozitioneaza componentele in functie de o grila cu numarul de randuri si de


coloane specificate la instantierea clasei managerului de pozitionare. Iata constructorii clasei
GridLayout:

GridLayout()
GridLayout(int randuri, int coloane)
GridLayout(int randuri, int coloane, int hgap, int vgap)

Asemenea celorlalti LayoutManagers explicati anterior si GridLayout prezinta atributele hgap si


vgap (distanta intre componente pe verticala si pe orizontala). De cele mai multe ori GridLayout este
construit cu ajutorul celui de-al doilea constructor din lista GridLayout(int randuri, int coloane).
Distanetele dintre componente pe orizontala si pe verticala pot fi setate si cu ajutorul mutatorilor:
36

setHgap(int gap)
setVgap(int gap)

Si numarul de randuri si de coloane poate fi modificat sau setat ulterior dupa instantierea obiectului.
Pentru aceasta exista mutatorii:

setColumns(int coloane)
setRows(int randuri)

Acestea fiind spuse sa incercam exemplificarea unei iterfete cu o fereastra pe care este setat
managerul GridLayout:
Dupa crearea unui nou proiect pe care l-am numit aplicatie4, am deschis un nou fisier Fereastra.java,
pentru dezvoltarea clasei Fereastra. Aceasta clasa mosteneste JFrame si are un atribut vector de
etichete. Obiectul eticheta este descris de clasa JLabel si foloseste la afisarea fie a unui text, fie a
unei imagini. Pe fereastra intentionez sa afisez 20 de etichete pe 4 randuri si 5 coloane. Pentru acesta
va trebui sa setez un manager de tip GridLayout initializat corespunzator.

GridLayout(4,5);

Imediat dupa setarea managerului de pozitionare initializez fiecare eticheta in parte si le adaug pe
toate cu ajutorul unei structuri de control repetitive "for";

37

Pentru a vedea rezultatul, in clasa principala (Main) voi instantia clasa fereastra si voi afisa fereastra
cu cele 20 de instante JLabel;

38

Etichetele pot fi folosite si pentru afisarea de imagini.

Pentru afisarea unei imagini avem nevoie de un obiect de tip Icon; Acesta este instantiat cu ajutorul
clasei ImageIcon;
Icon ico = new ImageIcon("animal.jpg");
Am adaugat imaginea corespunzatoare "animal.jpg" in directorul proiectului. Folosind constructorul
JLabel(Icon i) am instantiat clasa JLabel construind astfel o eticheta care afisaza o imagine.
Metoda setDefaulCloseOperation() careia i-am trimis ca argument JFrame.EXIT_ON_CLOSE
(constanta de tip int) se ocupa de inchiderea programului odata cu inchiderea ferestrei. Acesta
metoda este specifica clasei JFrame;

39

Daca dorim sa afisam pe eticheta respetiva atat text cat si o imagine vom folosi constructorul
JLabel(String s, Icon i, int horizontalAlignement)

40

Vom folosi eticheta (JLabel) de acum incolo ca instrument de iesire - modalitate de afisare a
rezultatelor.

1.6

Fereastre interioare - JInternalFrame si clasa Cursor

Probabil ca fiecare a folosit macar o data o aplicatie Microsoft Office. Sa luam drept exemplu
aplicatia Microsoft Word. La deschiderea unui document pentru editare text, editorul deschide in
interiorul aplicatiei reprezentata de o fereastra principala, o fereastra interioara in care se poate face
procesarea proproiu-zisa a continulului documentului. Aceasta lectie va prezenta in amanunt modul
in care putem dezvolta in java ferestre interioare ( altfel spus - ferestre in interiorul altor ferestre).
Pentru a dezvolta ferestre interioare avem nevoie de clasa JInternalFrame.
Cei mai importanti doi constructori pentru clasa JInternalFrame sunt:

public JInternalFrame(String titlu)


41

public JinternalFrame(String titlu, boolean resizable, boolean closable, boolean maximizable,


boolean iconifiable)

42

43

In acest fel am creat o fereastra interioara default. Aceasta nu se poate minimaliza si nici nu poate fi
redimensionata. Mai jos vom construi o fereastra interioara careia ii vom da permisiuni de
redimensionare si minimalizare.

De asemenea putem reprezenta fereastra printr-o iconita specifica:

44

Cu ajutorul clasei cursor putem seta aparitia unui anumit tip de cursor deasupra unei anumite
componente. Clasa Cursor are urmatorii doi constructori:

public Cursor(int tip)


public Cursor(String cursor)

Primul constructor creaza o instanta de cursor setata in sistemul de operare de un anumit tip. Iata
cateva constante ce definesc tipuri de cursor:

CROSSHAIR_CURSOR
DEFAULT_CURSOR
E_RESIZE_CURSOR
HAND_CURSOR
MOVE_CURSOR
TEXT_CURSOR
WAIT_CURSOR

Pe fereastra interioara creata anterior voi seta tipul de cursor WAIT_CURSOR:

45

1.7

Butoane de selectie si grupuri de butoane

Cu siguranta fiecare dintre voi a vazut si a folosit pana acum butoane de selectie.
Aceste butoane, dupa cum le spune si numele sunt folosite pentru selectarea a diferite optiuni
predefinite de catre utilizator.
Butoanele de selectie sunt de doua feluri: Checkbox si Radiobutton;
In principal butoanele de tip checkbox sunt definite separat pentru a se putea selecta mai multe
butoane, prin urmare mai multe optiuni date utilizatorului sunt disponibile simultan.
Butoanele radio sunt de obicei folosite pentru a nu permite utilizatorului sa selecteze decat o singura
optiune dintr-un grup.
Un exemplu mai concret ar fi:
Sa ne imaginam ca in setarile unui program pe care il cream trebuie sa oferim posibilitatea
utilizatorului de a schimba rezolutia monitorului in raport cu programul.

46

In acest caz ar trebui sa folosim butoane de tip radio, deoarece utilizatorul nu are voie sa selecteze
decat o singura rezolutie dintr-un grup de optiuni pe care il definesre programatorul.
Daca insa utilizatorul trebuie sa selecteze mai multe optiuni programatorul trebuie sa defineasca
pentreu acestea butoane de tip checkbox.

Clasa JCheckBox este cea care defineste butoanele de tip checkbox. Clasa JCheckBox face parte din
pachetul javax.swing; Iata cateva detalii despre clasa si constructor:
Cei mai importanti constructori ai clasei sunt urmatorii:

1. public JCheckBox()
2. public JCheckBox(String text)
3. public JCheckBox(String text, boolean selected)
47

Primul constructor creeaza un buton simplu, neselectat si fara o eticheta aplicata acestuia. Eticheta
este textul ce apare dupa buton si defineste optiunea care poate fi sau nu selectata de utilizator.

48

Cel de-al doilea constructor atasaza si o eticheta de tip text:

49

Cu ajutorul celui de-al treilea constructor se poate defini si starea butonului. Acesta poate fi selectat
sau neselectat. Daca cel de-al doilea argument al constructorului este true atunci butonul este selectat
iar daca acesta este false butonul ramane neselectat.

Mai multe butoane pot fi selectate simultan:

50

Butoanele de tip radio sunt definite de clasa JRadioButton.


Cei mai importanti constructori pentru clasa JRadioButton sunt:

1. public JRadioButton()
2. public JRadioButton(String text)
3. public JRadioButton(String text, boolean selectat)
Primul constructor creeaza un buton de tip radio fara textul de eticheta ce reprezinta optiunea ce
poate fi selectata de utilizator. Al doilea este constructorul care defineste instanta acestei clase
urmata de un text de eticheta.

51

Daca folosim cel de-al treilea constructor ca in exemplul primului buton din imaginea de mai sus
acesta functioneaza idem celui de la constructia instantei JCheckBox. Daca al doilea argument este
true butonul este predefinit selectat. Daca acesta este false el ramane neselectat.
O observatie interesanta este ca cele trei butoane din exemplul de mai sus nu se comporta asa cum
ne-am astepta sa se comporte niste butoane de tip radio. Acestea pot fi selectate mai multe. Pentru a
le face sa se excluda voi adauga butoanele unui grup de butoane:

52

In acest moment din grupul de butoane creat nu mai poate fi selectat decat unul singur odata. Grupul
de butoane este definit de clasa ButtonGroup ce apartine tot pachetului javax.swing;

1.8

Butoane de selectie

Putem clasifica in doua moduri butoanele de selectie:


Dupa numarul de optiuni care pot fi selectate:
1. cu selectie multipla - Clasele JCheckBox, JCheckBoxMenuItem
2. cu selectie simpla - Clasele JRadioButton, JRadioButtonMenuItem
Dupa amplasarea lor:
1. pe container - Clasele JChackBox si JRadioButton
2. in meniu - Clasele JCheckBoxMenuItem, JRadioButtonMenuItem
53

O alta clasa importanta atunci cand folosim butoane de selectie este ButtonGroup. ButtonGroup
permite adaugarea butoanelor de tip radio (folosite pentru selectie simpla) intr-un grup. Astfel, dintrun grup e butoane poate fi selectata o singura optiune. In imaginile de mai jos aveti exemple de
folosire ale celor patru clase enumerate mai sus care definesc tipuri de butoane de selectie:
JCheckBox:

54

55

Folosind consructorul care primeste ca al doilea parametru o valoare boolean putem preciza daca
butonul creat este implicit selectat sau nu.

56

JRadioButton:

57

58

Din pacate, dupa cum observati mai sus nu putem selecta o singura optiune chiar daca butoanele sunt
de tip radio. Pentru a crea un grup de butoane din care sa se poate electa numai o singura optiune se
poate folosi clasa ButtonGroup dupa cum puteti vedea mai jos:

59

JCheckBoxMenuItem:
Asa cum ii spune si numele clasa JCheckBoxMenuItem este o optiune de meniu. Aceasta
functioneaza similar clasei JCheckBox dar este construita pentru a atasa instantele unui meniu nu
unui panu sau unei ferestre:

60

61

JRadioButtonMenuItem:
Clasa JRadioButtonMenuItem functioneaza similar clasei JRadioButton, dar instantele acesteia
sunt create special pentru a putea fi adaugate pe meniuri. Tot cu ajutorul clasei ButtonGroup se poate
crea un grup de butoane JRadioButtonMenuItem din care se se poata selecta o singura optiune.

62

63

Se poate verifica daca un buton de selectie este selectat folosind comportamentul isSelected(). Daca
isSelected() returneaza true atunci butonul este selectat, in caz contrar acesta nu este selectat.

1.9

Clasa JComboBox

JComboBox este clasa cu ajutorul careia cream o lista drop-down. Cele mai des folosite
comportamente pentu clasa JComboBox sunt:

addItem(Object o) - adauga o optiune in lista


getSelectedItem() - preia optiunea selectata din lista
setEnabled(boolean flag) - seteaza lista ca activa sau inactiva in functie de parametru boolean
dat
setEditable(boolean flag) - seteaza permisiuhea de a edita in campl listei in functie de
parametru boolean dat

Mai jos aveti un exemplu de definire a unei liste:

64

65

Folosirea comportamentului setEditable():

66

1.10 Clasa JTable


Clasa JTable poate fi folosita pentru crearea unui tabel. Un tabel poate fi o metoda foare eficienta de
afisare sau chiar preloare de informatie de la utilizator. Un tabel creaza un mod de afisare a
informatiei ordonat ceea si permite afisarea datelor pentru entitiati similare find des folosit pentru
afisarea informatiilor dintr-o baza de date. Mai jos aveti un exemplu simplu de creare a unui tabel cu
date deja existente:

67

Crearea unui tabel cu un numar de randuri si de coloane predefinit fara informatii implicite poate fi
creat folosind constructorul:

public JTable(int rows,int cols) - primeste numarul de linii si de coloane prin parametrii si
creaza tabelul

68

Adaugarea unei valori in tabel folosind comportamentul setValueAt() :

69

1.11 Componente text


In aceasta lectie vom discuta despre clasele JTextField, JTextArea si JPasswordField care
reprezinta componente text folosite in diferite situatii pentru crearea intrfetelor grafice.
Clasa JTextField este folosita pentru introducerea de texte de dimensiuni mici. Componenta afisaza
un camp de text cu o singura linie. Crearea acesteia se face cel mai des folosind constructorul care
precizeaza si lungimea in coloane a componentei text sub forma unui parametru int:

70

71

JTextArea:
Componenta JTextArea afisaza un camp de text cu linii si coloane folosit in general pentru afisarea
sau introdcerea unui text de dimensiuni mai mari.

72

Un text poate fi setat in campul de text folosind metoda setText() care primeste ca parametru un
String reprezentand sirul de caractere ce va fi adaugat in componenta text. Textul din componenta
poate fi obtinut prin apelul comportamentului getText() care returneaza situl de caractere sub forma
unui String.
Clasa JTextArea are comportamentul append() care primeste ca parametru un String pe care il
adauga in campul text.
JPasswordField:
Clasa JPasswordField defineste un camp de text similar lui JTextField, doar ca acesta ascunde
caracterele introduse. Este folosit in principal pentru campuri in care sunt introduse parole.

73

1.12 Etichete - clasa JLabel


Clasa JLabel descrie probabil cea mai simpla componenta grafica - eticheta. O eticheta poate fi
folosita pentru a afisa un text sau un icon.

74

Afisarea unei imagini intr-o eticheta:

75

76

Modulul 2: Swing evenimente

2.1 Componente text: clasa JTextField


Vom studia trei tipuri de componente care ne ajuta sa introducem de tip text pentru a fi mai departe
procesate de aplicatie. Aceste componente sunt definite de clasele JTextField, JTextArea si
JPasswordField;
Clasa JTextField descrie un obiect de tip camp de text. Aceasta componenta definita tot in pachetul
javax.swing foloseste la introducerea de date text de dimensiuni mici. De exemplu la introducerea
unui text ce are de la unu pana la maximum cinci cuvinte este recomandata folosirea componentei
JTextFiled;
Iata cateva detalii despre clasa JTextField:
Cei mai importanti constructori:
1. public JTextField()
2. public JTextField(int col)
3. public JTextField(String s)
4.public JTextField(String s, int col)
Primul constructor creaza un cap de text fara lungime sau text initial. Acest constructor nu este in
principal folosit pentru definirea campului de text, dar reprezinta cel mai simplu construcotr al clasei
JTextField. Al doilea constructor este cel mai important. Acesta creaza un camp de text cu un numar
de coloane definit de atributul int dat ca argument constructorului:

77

Constructorul JTextField(String s) creaza o componenta camp de text ce contine predefinit un text


initial si are lungimea textului initial la constructie.

78

Exista si posibilitatea de a seta un text initial si o lungime a componentei diferita de cea a textului
initial. Pentru asta vom folosi ultimul constructor:

Cele mai importante metode ce definesc comportament al instantelor JTextField sunt getText() si
setText(String s). Aceste metode folosesc pentru preluarea textului dintr-un camp de text sub forma
de obiect String sau setarea unui text pentru instanta de JTextField.
Iata cum se poate folosi metoda getText();
JTextFIeld t = new JTextField("Text initial");
String s = t.getText();
// in acest moment variabila s retine textul "Text initial" pe care il contine si componenta text
Metoda setText(String s) primeste ca argument String-ul care trebuie atasat compoentei text;
t.setText("un text");
79

2.2 Componente text: clasa JTextArea


Componentele definite de clasa JTextArea sunt folosite pentru a introduce siruri de carecatere de
dimensiuni mai mari in program, care pot fi structurate pe mai multe linii. Componenta JTextArea
este foarte asemanatoare cu JTextField ca utilizare in cadrul programului pentru introducerea de date
String si/sau afisarea acestora.
Constructorii pe care ii vom folosi pentru instantierea clasei JTextArea sunt:
1. public JTextArea();
2. public JTextArea(String s);
3. public JTextArea(int rows, int cols);
4. public JTextArea(String s, int rows, int cols);
Primul constructor este folosit numai pentru definirea si initializarea unei componente JTextArea.
Aceasta nu va fi vizibila pe fereastra pana nu ii va fi seatata fie un numai de coloane si de randuri, fie
un text initial. In majoritatea cazurilor nu vom folosi primul constructor dintre cele enumerate mai
sus.
Constructorul 2, dintre cele enumerate creaza o componenta cu un numar de randuri si de coloane
initiale in functie de lungimea textului si pe cate linii este acesta scris. Iata definirea unei astfel de
componente pentru un text pe o singura linie:

80

Pentru a crea o componenta cu mai multe linii am folosit caracterul \n cu semnificatia new line.(linie
noua)
Iata si un exemplu de componenta creata cu un text initial pe mai multe linii:

81

Constructorul JTextArea(int rows, int cols) defineste o componenta JTextArea cu un numai initial de
randuri si de coloane fara a avea un text predefinit:

82

In imaginea de mai sus aveti exemul de instantiere a unei componente text cu 10 linii de 20 de
coloane, dar fara text initial. Daca dorim ca aceasta sa contina si un text initial vom folosi ultimul
constructor enumerat.

Metodele de peluare a textului dintr-o componenta JTextArea si de afisare a textului cu ajutorul


acesteia sunt indentice cu cele folosite pentru componenta JTextField;
Veti folosi in acest scop cele doua metode comportament: setText(String s) si getText();
Atat pentru componentele JTextField cat si pentru cele JTextArea putem seta ca textul sa se vada cu
un anumit font;
Pentru setarea unui font vom folosi metoda setFont(Font f);
Sa aruncam o privire asupra clasei Font. Clasa Font se afla in pachetul java.awt;
Pentru a crea un tip de font putem folosi constructorul: Font(String name, int style, int size)

83

Numele reprezinta numele fontului, stilul este dat ca o constanta ce apartine clasei Font, iar size
reprezinta marimea textului.
Cateva constante folosite frecvent din clasa Font sunt:

BOLD
ITALIC
MONOSPACED
PLAIN
SANS_SERIF
ROMAN_BASELINE
TRUETYPE_FONT

Sa incercam sa schimbam fontul pentru aplicatia anterioara:

Se observa in imaginea de mai sus ca textul din componenta JTextArea si-a modificat fontul;

84

2.3 Componente text: clasa JPasswordFiled


Componenta JPasswordField descrisa de clasa cu acelasi nume ce apartine pachetului java.swing este
foarte asemenatoare cu componenta JTextField; Diferenta dintre cele doua componente este ca
JPasswordField ascunde caracterele textului din componenta. Instantele clasei JPasswordField sunt
folosite pentru formulare de login in special la scrierea parolei, pentru a ascunde (masca) caracterele
astfel incat sa asigure securitate impotriva indentificarii acesteia.
Constructorii folositi cel mai des pentru instantierea clasei JPasswordField sunt:
1. JPasswordField(int cols)
2. JPasswordField(String s)
3. JPasswordField(String s,int cols);
Primul constructor ceaza o instanta de JPasswordField cu un numar de coloane predefinit, dar fara un
text initial;

85

Constructorul JPasswordField(String s) creaza o componenta JPasswordField cu un text initial si


lungime predefinita egala cu lungimea textului initial:

86

Metodele care pot fi folosite pentru preluarea sirului din componenta text este fie getText(), metoda
ce returneaza sirul sub forma unei instante String sau getPassword(), metoda ce returneaza sirul de
caractere sub forma unui vector de primitive char[]

2.4 Meniuri
Pentru a dezvolta o aplicatie cu un meniu simplu avem nevoie de cel putin trei clase care descriu
componente indispensabile. Aceste clase apartin pachetului javax.swing si se numesc: JMenuBar,
JMenu si JMenuItem;

87

Pentru inceput cream o instanta de JMenuBar. Aceasta este bara de meniu din partea de sus a
ferestrei pe care sunt asezate mai multe meniuri. In cazul aplicatiei din exemplu nu am atsat barei de
meniu decat meniul "File". Un meniu este definit de clasa JMenu. Textul ce reprezinta numele
meniului se da ca argument sub forma de String la instantierea clasei:
JMenu m1 = new JMenu("File");
Cu ajutorul metodei add() putem adauga meniul pe bara de meniu. Bara de meniu se adauga pe
fereastra folosind metoda setJMenuBar(JMenuBar mb).

f.setJMenuBar(mb);
mb.add(m1);

88

Pe un meniu se pot aduga alte meniuri sau instante ale clasei JMenuItem. In exemplul anterior
"New..." este un JMenuItem.
JMenuItem mi1 = new JMenuItem("New...");
Un menu item poate fi adaugat pe un meniu tot cu ajutorul metodei add()
m1.add(mi1);
In imaginea de mai jos aveti un exemplu de aaugare a unui meniu in interiorul unui alt meniu:

In acest submeniu pot fi adaugate alte submeniuri definite tot cu ajutorul clasei JMenu sau instante
de JMenuItem:

89

Pentru a separa vizual mai multe elemente intr-un meniu putem folosi metoda addSeparator().
Aceasta metoda de separare a elementelor unui meniu este utila gruparii acestora dupa functiile lor:

90

Se poate observa in imaginea de mai sus efectul folosirii metodei addSeparator() intre cele doua
instante de JMenuItem "Open" si "Exit";
Pentru executarea unei actiuni la apasarea unui element al unui meniu se procedeaza exact ca in
cazul butoanelor. Acestea reactioneaza la evenimente de tip ActionEvent. In imaginea urmatoare
aveti un exemplu de inchidere a aplicatiei la apasarea elementului "Exit" din meniul "File" :

Desigur, nu uitati ca aveti nevoie si de importarea pachetului java.awt.event; In aces moment, dupa
compilare si executie fereastra ar trebui sa se inchida dupa apasarea elementului "Exit" din meniul
"File";
Exista de asemenea posibilitatea de a inlocui apasarea elementului din meniu cu apasarea unei
combnatii de taste pentru executarea instructiunilor. Pentru aceasta vom folosi metoda
setAccelerator(KeyStroke ks) in urmatorul fel:
KeyStroke ks = KeyStroke.getKeyStroke("control alt X"); // "control alt X" adica ctrl-alt-X
mi3.setAccelerator(ks);
Argumentul String dat metodei getKeyStroke() poate fi spre exemplu:

control alt X
control X
control shift X
alt shift X
91

shift X

etc ...
In loc de "X" poate fi orice alt caracter, iar variatiunile intre <<control>> <<alt>> si <<shift>> pot fi
diverse;
In imaginea de mai jos aveti si modul de aplicare in exemplu direct:

In acest exemplu aplicat pe programul creat anterior, programul ar trebui sa se inchida ala apasarea
tastelor CTRL-ALT-X;
Iata si modul in care arata acum componenta JMenuItem:

92

Daca dorim ca o instanta de JMenuItem sa nu mai fie activa vom folosi metoda setEnabled(boolean
b); In functie de valoarea parametrului b componenta careia i se aplica comportamentul va fi activa
sau nu; b poate avea valoare true, caz in care componenta este activa sau false, caz in care aceasta se
dezactiveaza; Sa incercam dezactivarea componentei JMenuItem "New":

93

Se observa ca instanta JMenuItem devine inactiva si nu mai poate fi selectata;

2.5 Clasa JMenuItem si alte evenimente care pot fi aplicate


O instanta de JMenuItem poate sesiza si alte tipuri de evenimente decat cele ActionEvent. De
exemplu un JMenuItem poate sesiza evenimente de miscare a mouse-ului cu butonul apasat desupra
acestuia; Pentru a putea construi o instanta de JMenuItem care sesizeaza astfel de evenimente este
necesar mai intai sa importam pachetul javax.swing.event; Mai jos in imagine aveti exemplul de
atasare a unui ascultator pentru o instanta de JMenuItem. Atasarea ascultatorului se face cu ajutorul
metodei: addMenuDragMouseListener()
Metodele care se executa la intalnirea evenimentelor mouse-ului sunt:

94

public void menuDragMouseEntered(MenuDragMouseEvent e) - pentru intrarea cursorului desupra


componentei
public void menuDragMouseExited(MenuDragMouseEvent e) - pentru iesirea cursorului
public void menuDragMouseDragged(MenuDragMouseEvent e) - pentru tragerea cursorului
public void menuDragMouseReleased(MenuDragMouseEvent e) - pentru eliberearea butonului
mouse-ului desupra componentei

In exemplul de mai sus am afisat cate un mesaj diferit la intalnirea diferitelor evenimente ale mouseului;
Instantele de JMenuItem pot fi facute sa sesizeze si evenimentele tastelor. Pentru aceasta vom folosi
metoda: addMenuKeyListener()

95

Pentru sesizarea diferitelor tipuri de evenimente vom suprascrie urmatoarele metode:


public void menuKeyTyped(MenuKeyEvent e) - pentru apasarea si eliberarea unei taste
public void menuKeyPressed(MenuKeyEvent e) - pentru apasarea unei taste
public void menuKeyReleased(MenuKeyEvent e) - pentru eliberarea unei taste

Iata exemplul in care am afisat un mesaj in functie de un eveniment al tastelor; Nu uitati sa trebuie
mai inati selectata componenta pentru a sesiza evenimentele tastelor; (ca in imagine)

96

Un ultim tip de eveniment pe care il poate sesiza o componente JMenuItem este daca utilizatorul il
selecteaza sau nu; Iata cum procedam pentru acest tip de verificare:

La construirea obiectului va trebui sa suprascriem metoda menuSelectionChanged(boolean selectat) ;


In interiorul acesteia putem executa o anumita instructiune daca acesta este selectat sau nu; De
exemplu, in imaginea anterioara am afisat in consola mesajele "selectat" si "neselectat";

2.6 Modificari ce pot fi aduse componentelor JMenuItem


Mai jos puteti vedea un tabel cu toate atributele ce pot fi modificate pentru componente JMenuItem.
Pentru fiecare dintre acestea exista o functie mutator pentru modificarea valorii acesteia:

Proprietate

Tipul obiectului
97

MenuItem.acceleratorDelimiter
MenuItem.acceleratorFont
MenuItem.acceleratorForeground
MenuItem.acceleratorSelectionForeground
MenuItem.actionMap
MenuItem.arrowIcon
MenuItem.background
MenuItem.border
MenuItem.borderPainted
MenuItem.checkIcon
MenuItem.commandSound
MenuItem.disabledForeground
MenuItem.font
MenuItem.foreground
MenuItem.margin
MenuItem.opaque
MenuItem.selectionBackground
MenuItem.selectionForeground
MenuItem.textIconGap
MenuItemUI

String
Font
Color
Color
ActionMap
Icon
Color
Border
Boolean
Icon
String
Color
Font
Color
Insets
Boolean
Color
Color
Integer
String

Aveti un exemplu in imagine de modificarea a culorii foreground-ului (textul de pe JMenuItem):

Pentru aceasta am folosit mutatorul setForeground();

98

2.7 Elemente de meniu selectabile


Un meniu poate contine si elemente ce pot fi selectate, in vederea bifarii unei optiuni. Aceste
elemente sunt create cu ajutorul claselor JCheckBoxMenuItem si JRadioButtonMenuItem. Aceste
clase descriu obiecte asemanatoare celor descrise de clasele JCheckBox si JRadioButton, dar se
adauga numai ca elemente ale unui meniu, deci folosind metoda add() pe o instanta de JMenu; In
imaginile de mai jos aveti exemplul folosirii celor doua tipuri de componente pentru crearea unei
aplicatii.

99

Aidoma butoanelor de tip checkbox descrise de clasa JCheckBox din pachetul javax.swing acestea
sunt folosite pentru o lista de optiuni cu posibilitate de selectare multipla. Butoanele sunt in general
insotite de un label care poate fi un text sau o imagine ce descrie optiunea ce poate fi bifata de
utilizator. In imaginile de mai jos aveti exemplul crearii unei astfel de componente cu un label de tip
imagine:

100

101

102

Asemanatoare la constuctie sunt butonele de meniu de tip JRadioButtonMenuItem. Acestea sunt in


gereal foloste pentru descrierea unei liste de optiuni din care utilizatorul poate selecta o singura
optiune. Pentru realizarea acestei constrangeri este necesara folosirea unei instante a clasei
ButtonGroup; Aveti exemple de definire a unui meniu cu optiuni de tip JRadioButtonMenuItem in
imaginile de mai jos;

103

104

2.8 Selectarea fisierelor cu interfata grafica JfileChooser

2.8 Selectarea fisierelor cu interfata grafica - JFileChooser

105

106

107

2.9 WindowListener si WindowEvent


Interfata WindowListener defineste urmatoarele sapte metode pentru evenimente specifice
ferestrelor:

windowActivated(WindowEvent ev) - apelat la activarea ferestrei


windowDeactivated(WindowEvent ev) - apela la dezactivarea ferestrei
windowIconified(WindowEvent ev) - apelat la scoaterea ferestrei din bara de task
windowDeiconified(WindowEvent ev) - apelat la punerea ferestrei in bara de task
windowOpened(WindowEvent ev) - apelat dupa deschiderea ferestrei
windowClosed(WindowEvent ev) - apelat dupa inchiderea ferestrei
windowClosing(WindowEvent ev) - apelat la incercarea de inchidere a ferestrei

Similar cu MouseAdapter exista si clasa WindowAdapter, care permite suprascrierea numai


metodelor necesare:

108

2.10 Paleta de culori


Paleta de culori este o componenta ce permite utilizatorului selectarea unei culori, visual din cele
2563 culori posibile cu standardul RGB. Paleta de culori este construita cu ajutorul clasei
JColorChooser. In general insa din clasa JColorChooser este folosita pentru a defini o paleta de
culori intr-o fereastra de dialog metoda showDialog() care este definita static. In exemplul de mai jos
la apasarea pe butonul culori se deschide o fereastra cu paleta de culori si este setata culoarea de
fundal a butonului in culoarea selectata din paleta.

109

Metoda showDialog() returneaza o instanta de java.awt.Color care reprezinta culoarea selectata daca
utilizatorul a selectat o culoare sau culoarea implicita daca acesta a apasat Cancel.

110

2.11 Fereastra de selectare din sistemul de fisiere


Exista posibilitatea de a crea o fereastra de selectare a unui fisier din sistemul de fisiere folosind
clasa JFileChooser. Comportamentul JFileChooser ce se numeste showOpenDialog() poate fi folosit
pentru crearea unei ferestre de dialog de deschidere. Metoda showSaveDialog() poate fi folosita
111

pentru crearea unei ferestre de dialog de salvare. Dupa selectarea unui fisier pentru salvare sau
deschidere in functie de metoda folosita fisierul poate fi preluat din instanta JFileChooser cu ajutorul
metodei getSelectedFile() sub forma unei instante java.io.File;
In exemplul de mai jos textul continut de campul JTextArea poate fi salvat in fisier:

112

113

Similar se poate selecta un fisier pentru deschidere folosind metoda showOpenDialog() in loc de
showSaveDialog().

114

Modulul 3: MySQL Notiuni de baza

3.1 Instalarea serverului MySQ


Pentru a putea crea baze de date este necesar mai intai sa instalam un server pe computerul pe care
urmeaza sa dezvoltam aplicatia. In acest curs am ales sa folosim MySQL ca tip de limbaj pentru
dezvoltarea bazelor de date, acesta fiind cel mai utilizat, dar si cel mai simplu de invatat; Asemanator
modului in care urmeaza sa dezvoltam aplicatii Java cu MySQL se pot dezvolta si aplicatii Java cu
alte dipuri de baze de date. In urmatoarele trei modul nu ne vom mai ocupa de Java, ci vom trece in
revista bazele de date pentru a intelege atat notiunile fundamentale cat si modul de aplicare al
acestora in vederea crearii aplicatiilor de baze de date cu interfata grafica creata cu Java;
Iata cum incepem lucrul cu baze de date MySQL; Mai intai trebuie sa intelegem faptul ca bazele de
date sunt stocate si procesate de o aplicatie server. Exista mai multe kit-uri software cu ajutorul
carora se poate instala MySQL pe o platforma. Am ales ca in acest curs sa descriu modul de instalare
al aplicatie XAMPP. Aceasta aplicatie instaleaza un server Apache cat si un server MySQL. Serverul
MySQL functioneaza pe portul 3306;
Pentru inceput downloadati kit-ul de instalare; Imaginile de mai jos va arata pasii instalarii acestui kit
pe platforma sistemului de operare Windows.

115

Default aplicatia de administrare xampp se instaleaza in directorul C:\xampp ; In acest director


cautati executabilul xampp-control.exe ; Acesta va deschide o mica fereastra din care aveti
posibilitatea de a deschide sau de a inchide procesele serverelor instalate; Va finecesar sa pornim
serverele Apache si MySQL; Aceasta se poate face prin simpla apasare a butoanelor "START" din
dreptul fiecaruia;

116

Dupa pornire verificati ca statusul celor doua servere sa fie "Running" , ca in imaginea de mai sus;
Vom incepe dezvoltarea bazelor de date folosind aplicatia PHP gratuita numita phpmyadmin ce se
instaleaza odata cu instalarea xampp. Aplicatia phpmyadmin se poate accesa dupa deschiderea
serverelor Apache si MySQL din orice browser accesand adresa 127.0.0.1/phpmyadmin; IP-ul
127.0.0.1 este cunoscut si sub numele de ip de loopback si este adresa care face referire catre
sistemul de unde se face accesarea;

117

3.2 Entitati

O baza de date reprezinta o colectie de entitati ce interrelationeaza. O entitate reprezinta o colectie de


atribute identificate printr-o cheie unica numita PRIMARY KEY. Aceasta cheie unica sau cheie
primara este cea care identifica o inregistrare. Numele entitatii denumeste practic ceea ce noi
inregistram intr-o anumita zona a bazei de date. De exemplu putem construi entitatea Student.
Entitatea Student ar putea avea urmatoarele atribute:

cnp
nume
prenume
facultate
grupa
an
data_nasterii

Dintre atributele pe care le-am enumerat ci care pot descrie entitatea Student "cnp" ar putea fi cel
care sa devina si cheie primara a acestei entitati; De ce? Pentru ca este singurul atribut ce ia valori
unice in functie de fiecare entitate de student inregistrata. Practic "cnp" este singurul atribut care cu
siguranta va fi unic fiecarui student in baza noastra de date.
Oricare dintre celelalte atribute pe care le-am ales se pot avea valori diferite pentru diferite
inregistrari. De exemplu pot exista doi sau mai multi Studenti cu numele George; Pot exista doi sau
mai multi studenti nascuti in aceeasi zi si cu siguranta mai multi studenti vor apartine aceleiasi
facultati sau aceleiasi grupe;
Mai jos aveti modul de descriere schematic al unei entitati. O entitate este denumita de obicei cu un
substantiv la singular (Ex. Student, Animal, Structura, Cont etc.). Acesta este desenata cu un
dreptunghi cu colturi rotunde denumit "soft-box". Acest dreptunghi incadreaza atributele entitatii.
Atributele pot fi marcate cu trei simboluri: #, o sau *;
# - inseamna ca atributul este primary key
o - inseamna ca atributul este mandatory (obligatoriu)
* - inseamna ca atributul nu are restrictii

118

Cheia primara "cnp" dupa care am ales sa identificam inregistrarile entitatii Student se numeste cheie
primara cu caracter real; De obicei atributele cu caracter real nu sunt folosite ca primary key. Pentru
oricare entitate pe care o vom crea vom defini un atribut numit "id", care va avea rol de cheie
primara si care va fi un numar incrementat pentru fiecare inregistrare noua. Acest mod de creare a
cheii primare se numeste "cheie primara cu caracter artificial".

3.3 Baze de date


Bazele de date reprezinta o colectie de entitati ce relationeaza intre ele. Relationarile intre entitati pot
fi de trei feluri la dezvoltarea acestora:

one-to-one (unu la unu)


one-to-many (unu la mai multi)
many-to-many (mai multi la mai multi)

Aceste inter-relationari sunt gandite in momentul in care dezvoltam baza de date teoretic. Pentru
dezvolotarea bazei de date este necesar mai apoi sa ajustam relatii intre entitati astfel incat sa nu
existe relatii many-to-many, acestea fiind dificil de controlat in momentul executiei programului de
interfatare pe care il dezvoltam cu java. Ralatiile intre entitati se fac prin intermediul cheilor primare
si se pot referi la oricare dintre atributele entitatilor care relationeaza.

3.4 Relatii one-to-one


119

Relationarea unu-la-unu este cel mai simplu tip de relatie intre doua entitati. Pentru a intelege acest
tip de relationare vom presupune urmatoarele doua entitati:

Culoare
Birou

Entitatea birou are urmatoarele atribute:


# id
o nume
o cod_birou
Entitatea persoana are urmatoarele atribute:
#id
o cnp
o nume
o preume
o birou
Iata cum presupunem relationare intre cele doua entitati; Compania care detine aceasta baza de date
are angajate persoane; Fiecare persoana are disponibil un birou si numai unul, iar in fiecare birou
trebuie sa lucreze o singura persoana. Acesta este un exemplu de relationare unu-la-unu. Practic,
atributul birou al entitatii persoana va retine id-ul (primary key) al biroului in care lucreaza. Este
suficient pentru a face relationare unu-la-unu necesara. In acest fel retinem datele fiecareui birou, si ,
prin intermediul entitatii persoana ii atribuim o persoana care sa lucreze in acea locatie.
Iata inca un exemplu pentru a intelege relationare unu-la-unu. Sa presupunem entitatile Medic si
Halat; Orice medic are un sigur halat oferit de spitalul la care lucreaza, dar halatul trebuie sa fie
purtat doar de medicul care il detine.
Halat:
#id
o culoare
o marime
Medic
#id
o nume
o prenume
o halat
Atributul halat al entitatii medic va retine numarul id-ului halatului pe care il detine; O observatie
importanta este faptul ca desi eu am notat cu "id" ambele chei primare ale entatiatilor Medic si Halat,
acestea sunt diferite si nu au nicio legatura una cu cealalta. Ambele au roluri diferite, deoarece una
indexeaza inregistrarile din entitatea Medic, iar celalata inregistrarile din entitatea Halat;

120

3.5 Relatii one-to-many


Relatiile unu la mai multi sunt probabil cele mai intalnite tipuri de relationari la dezvoltarea bazelor
de date. Acest lucru se intampla deoarece, asa cum vom vedea in urmatoarea lectie, fiecare relatie
many-to-many se desparte pentru a o putea controla la programare in doua relatii one-to-many. Mai
jos voi da un exemplu de relationare unu la mai multi;
Sa presupunem entitatile Elev si Scoala:
Elev
# id
o nume
o prenume
o scoala
o cnp
Scoala
#id
o locatie
o nume
Un elev nu poate fi inscris decat la o singura scoala, dar o scoala are inscrisi multi elevi; Din modul
in care am formulat propozitia de relationare indica clar faptul ca relatia este unu la mai multi.
Fiecare elev va avea stocat in atributul "scoala" id-ul (primay key) scolii la care este inscris, dar este
posibil ca mai multi elevi sa aiba acest atribut egal. Diferenta intre relationarea one-to-one si one-tomany este ca atributul ce facea relationarea, in cazul relationarii unu-la-unu acesta era unic, spre
deosebire de relationarea one-to-many, unde se observa ca acesta nu mai are cum sa fie unic;

3.6 Relatii many-to-many


Exista cazuri in dezvoltarea bazelor de date in care observam ca doua entitati relationeaza sub format
many-to-many. Este foarte dificil sa controlam la programare aceste tipuri de relatii, prin urmare,
dupa dezcrierea lor in format many-to-many este necesar sa le transformam in relatii one-to-many
prin introducerea de entitati de mediere. Iata mai intai un caz de relationare many-to-many pe care sa
il discutam in vederea intelegerii acestuia:
Preuspunem entitatile Elev si Profesor. Inca inaine dezvoltarii entitatilor realizam ca intre acestea va
exista o relationare many-to-many. Un elev are mai multi profesori, si un profesor are mai multi
elevi; Teoretic este usor de imaginat, dar la dezvoltarea entitatilor vom observa ca este dificil de
facut practic relationare intre cele doua entitati;
Profesor
#id
o nume
121

o prenume
o materie
o elev
Elev
#id
o nume
o prenume
o cnp
o profesor
Observam ca daca cele doua entitati ar fi descrise in acest fel, pentru fiecare profesor ar trebui sa
facem mai multe inregistrari, in functie de cati elevi are, iar pe fiecare elev ar trebui sa il inregistram
de atatea ori cati profesori are. Acest lucru ar insemna pierderea unicitatii fiecarei inregistrari. Este
practic inposibil de facut practic aceasta relationare in vederea dezvoltarii unei baze de date fiebile.
Iata prin urmare ce modificari vom face pentru ca fiecare inrgistrare de entitate Elev sau Profesor sa
isi pastreze unicitatea:
Profesor
#id
o nume
o prenume
o materie
Elev
#id
o nume
o prenume
o cnp
Registru
#id
o profesor
o elev
Am scos atributele elev si profesor ale entiatilor initiale. Mai apoi am dezvoltat entitatea Registru
care are rolul de mediere intre cele doua entitati Elev si Profesor. Practic, nu inregistram decat datele
fiecarui elev si a fiecarui profesor, apoi in Registru facem referintele necesare intre inregistrari;

3.7 Dezvoltarea eficienta a entitatilor


Pentru a crea o baza de date fiabila entitatile pe care le dezvoltam trebuie gandite astfel incat sa nu
ingreuneze procesarea si odata cu asta sa micsoreze pe cat se poate timpul de accesare a datelor;
122

De exemplu, o regula importanta la dezvoltarea entitatilor este: unicitatea atributelor; O gresala


majora pe care o fac incepatorii la dezvoltarea bazelor de date este, uneori sa piarda unicitatea
atributelor unei entitati; Sa preuspunem urmatorul exemplu:
Pentru dezvoltarea unui magazin online, urmeaza sa dezvoltam entitatea Produs; Fiecare produs este
descris de un anumit numar de imagini pe pagina acestuia. Sa presupunem ca fiecare produs este
descris de cate patru imagini care il prezinta in vederea impresionarii clientului; Un incepator ar fi
tentat sa dezvolte entitatea Produs in felul urmator:
Produs
#id
o nume
o greutate
- imagine1
- imagine2
- imagine3
- imagine4
o stoc
Acest mod de descriere al entitatii Produs este gresit, deoarece atributul "imagine" isi pierde
unicitatea; Ganditi-va ca un produs poate avea maximum 4 imagini aferente, dar poate sa nu aiba
decat poate una sau doua. Eu nu cunosc cu exactitate daca un produs este descrid de 0,1,2,3 sau 4
imagini. Prin urmare la programarea aplicatiei de foloseste aceasta baza de date va fi mult mai dificil
de avut in vedere toate aceste atribute decat in situatia dezvoltarii entiatatii produs fara pierderea
unicitatii atributului "imagine"; In continuare voi prezenta modul in care se poate rezolva acest tip de
eroare:
In aceasta situatie vom dezvolta o entitate se parata Imagine si o entitate Produs:
Produs
#id
o nume
o greutate
- imagine
o stoc
Imagine
#id
o adresa
o descriere
o produs
Paractic am transformat entitate in doua entitati ce relationeaza one-to-many. O imagine poate
apartine unui singur produs, iar un produs poate avea mai multe imagini. In acest fel se observa si
faptul ca niciuna din entitati nu prierde unicitatea atributelor ei;

123

O alta gresala care se poate face este asignarea unor atribute entitatilor care se pot deuce unul din
altul. Exemplu - in vederea atributului Angajat
Angajat
#id
o nume
o prenume
o data_nasterii
o varsta
La dezvoltarea acestei entitati am asignat atributele "data_nasterii" si "varsta". In acest caz atributul
"varsta" este inutil asignat, deoarece varsta unu angajat se poate afla folosind atributul
"data_nasterii".

3.8 Erori in design-ul bazei de date


Exista trei tipuri principale de erori care se pot face la design-ul unei baze de date:
1. crearea de campuri multiple pentru acelasi tip de inregistrare
2. introducerea de informatii redundante
3. crearea buclelor in relatii
1. Crearea de campuri multiple este exemplificata in imaginea de mai jos. Pentru o persoana este
necesara stocarea mai multor numere de telefon. Modalitatea aleasa de programator in imaginea de
mai jos este gresita:

124

In imainea de mai sus sunt create trei campuri pentru stocarea unui singur tip de informatie: numarul
de telefon. Modalitatea aleasa este gresita, deoarece nu permite flexibilitate. In locul acestei abordari
ar fi trebuit creata separat o tabela telefoane care sa relatoneze one-to-many cu tabela persoane:

2. Intrducerea de informatii redundante se refera la adaugarea unui camp intr-o tabela care retine o
informatie ce poate fi obtinuta folosind valoarea altui camp. De exemplu tabela persoane de mai jos
contine campul varsta care este redundant, deoarece exista un camp numit data_nasterii cu ajutorul
caruia se poate afla foarte usor varsta:
125

3. Crearea buclelor in relatii apare in momentul in care o entitate relationeaza cu alte doua entitati
care au o relatie intre ele prin aceleasi chei externe. In acest caz una dintre relatii este suplimentara,
ea putand fi dedusa din celelalte doua.

126

Modulul 4: MySQL Interogari

4.1 Tabele, relatii si chei primare


Pana in momentul de fata ne-am referit la entitati si relatii in vederea dezvoltarii unei baze de date.
Teoretic (adica pentru conceperea schematioca a bazei de date in vederea dezvoltarii ei) acestea sunt
informatiile pe baza carora voi puteti dezvolta baze de date, practic vom schimba cateva notiuni
pentru a dezvolta o baza de date;
In cazul dezvoltarii practice a bazei de date entitatile noastre vor deveni tabele. Atributele
entitatilor vor deveni coloane in tabel. Prin urmare un astfel de tabel dezvoltat va avea ca randuri,
inregistrari ale diferitelor entitati;
Sa presupunem o entitate dezvoltata anterior:
Elev
#id
o cnp
o nume
o prenume
o scoala
o varsta
Entitatea Elev va deveni tabela cu numele Elevi. Aceasta tabela va avea coloanele id, cnp, nume,
prenume, scoala si varsta, unde id va fi cheie primara (adica atributul unic ce identifica fiecare
inregistrare) si celelalte atribute cu valoare obligatorie (not null);
In tabela fiecare atribut este de un anumit tip de data. Tipurile de date le clasificam in:
1.
2.
3.
4.

Numeric
Date and Time
String
Spatial

Tipurile numerice sunt:


1. TINYINT
2. SMALLINT
3. MEDIUMINT
4. INT
5. BIGINT
6. DECIMAL
7. FLOAT
8. DOUBLE
9. REAL
10. BIT
127

11. BOOL
12. SERIAL
Tipurile date and time sunt:
1.
2.
3.
4.
5.

DATE
DATETIME
TIMESTAMP
TIME
YEAR

Tipurile pentru siruri de caractere sunt:


1.
2.
3.
4.
5.
6.
7.
8.
9.

CHAR
VARCHAR
TINYTEXT
TEXT
MEDIUMTEXT
LONGTEXT
TINYBOLB
BOLB
LONGBOLB

Tipurile de date spatiale definesc puncte sau figuri geometrice regultate sau neregulate; In general
dintre toate tipurile de date enumerate la acestcurs vom folosi:

INT - numere intregi


FLOAT - numere reale
DOUBLE - numere reale
DATE - data
DATETIME - data si ora
TEXT - text de lungime mica
LONGTEXT - text de lungime mare

In principal vom prefera crearea relatiilor dintre entitati (acum tabele) prin interfata programata.
Exista posibilitatea de a relationa tabelele prin instructiuni SQL lacrearea tabelelor, dar, din motive
didactice voi prezenta relationarea tabelelor prin intermediul interfetei programate in Java.
Cheia primara sau unicitatea unui atribut reprezinta proprietati ale coloanelor in tabela ce reprezinta
o anumita entitate. Acestea se seteaza la crearea unei tabele.

4.2 Crearea unei tabele in aplicatia phpMyAdmin


Pentru inceput voi prezenta in paralel sintaxa limbajului MySQL cu utilizarea aplicatiei de consola
phpMyAdmin. Aplicatie phpMyAdmin va va ajuta sa creati si sa utlizati baze de date fara a lucra
direct cu monitorul MySQL; Aveti mai jos modul in care am construit baza de date cu numele
MyDataBase. Nu uitati sa porniti serverele Apache si MySQL din consola XAMPP pentru a putea
128

lucra cu aplicatia phpMyAdmin si cu serverul de baza de date. Aplicatia phpMyAdmin se acceseaza


printr-un web browser folosind fie adresa URL http://localhost/phpmyadmin fie
http://127.0.0.1/phpmyadmin.
Dupa intrarea in aplicatie completati campul corespunzator crearii bazei de date cu numele pe care
doriti sa il dati bazei de date (in cazul nostru MyDataBase).

Syntaxa in limbaj MySQL pentru crearea unei baze de date este:


CREATE DATABASE `<nume_baza_de_date>` ;

129

Pentru carearea tabelei Elevi din lectia anterioara vom completa in continuare caseta de text
corespunzatoare numelui tabelei pe care o cream si numarul de campuri (coloane) pe care le va avea
tabela; In cazul nostru tabela urmeaza sa aiba 6 campuri;

130

Completam fiecare cam cu informatiile (proprietatile) corespunzatoare acestuia: nume, tip de data
etc.

131

Observati faptul ca am marcat campul id ca fiind primary key;

132

4.3 Adaugarea unei noi inregistrari in tabela


Dupa crearea unei tabele in baza de date putem incepe sa adaugam inregistrari. Fiecare inregistrarea
reprezinta un rand dintr-o tabela. In oricare tabela inregistrarile sunt diferentiate de cel putin un camp
( cheia primara ). Pentru adaugarea unei inregistrari vom folosi instructiunea MySQL - INSERT.
Sintaxa pentru adaugarea unei inregistrari este:
INSERT INTO <nume_tabela> (`camp1`,`camp2`,`camp3` ...) VALUES
('valoare1','valoare2','valoare3',...);
Uneori o sa intalniti precizata si baza de date din care face parte tabela in care se face inregistrarea:
INSERT INTO <baza_de_date>.<nume_tabela> (`camp1`,`camp2`,`camp3` ...) VALUES
('valoare1','valoare2','valoare3',...);
In ceea ce priveste sintaxa trebuie sa fiti atenti la simbolurile care incadreaza identificatorii si
valorile care se atribuie; Identificatorii sunt incadrati de apostroafe ( ` ) in timp ce valorile care sunt
atribuite se incadreaza cu ghilimele simple ( ' );
Sa vedem modul in care introducem date folosind interfata grafica a aplicatiei phpmyadmin;

133

134

4.4 Vizualizarea inregistrarilor din tabele


Este important sa introducem informatie in baza de date, dar la fel de important este sa preluam
informatia din tabelele construite in vederea procesarii acestora. Preluarea informatiilor din tabele se
face folosint instructiunea SELECT;
Instructiunea SELECT are urmatoarea sintaxa generala:
SELECT <nume_coloana1>, <nume_coloana2> ... FROM <nume_tabela>;
Se pot selecta anumite atribute ale inregistrarilor din tabela al carei nume il precizam. Aceasta
sintaxa selecteaza valorile atributelor precizate ale tuturor inregistrarilor din tabela al carei nume il
precizam; Putem selecta spre exemplu toate valorile atributelor tuturor inregistrarilor folosind
sintaxa:
SELECT * FROM <nume_tabela>
Operatorul * inlocuieste scrierea tuturor numelor coloanelor; Selectarea tuturor inregistrarilor din
tabela folosind aplicatia phpmyadmin se face prin sectiunea browse dupa selectarea tabelei
corespunzatoare:

135

4.5 Conditionarea selectarii informatiilor din tabele dupa atribute


De cele mai multe ori nu veti avea nevoie de toate inregistrarile dintr-o tabla ci doar de cateva cu un
atribut comun. De exemplu sa presupunem ca dezvoltam o aplicatie de pentru o banca in care sunt
stocati clientii si conturile acestora. La un moment dat functionarul bancii doreste sa vizualizeze
conturile cu o suma de bani mai mare de 1000 de lei. Pentru a rezolva aceasta problema putem folosi
o sintaxa MySQL a instructiunii SELECT:
SELECT <coloana1>, <coloana2>, ... FROM <tabela> WHERE <coloana_conditie> <operator>
<valoare>;
Instructiunea de mai sus are urmatorul rol: Selecteaza randurile (inregistrarile) din tabela data in
functie de o anumita operatie;
Operatorii care se folosesc in astfel de situatii sunt in general:

=
LIKE
NOT LIKE
!=
IS NULL
IS NOT NULL

Operatorii = si != testeaza egalitatea exacta si sunt in general folositi pentru compararea valorilor
numerice sau datelor; Operatorii LIKE sau NOT LIKE sunt folositi pentru compararea valorilor de
tip siruri de caractere; Ultimii doi operatori enumerati nu necesita precizarea unei valori, acestia
avand rolul doar de a verifica daca inregistrarea are campul respectiv null sau non-null;
Exemplu:
SELECT * FROM `elevi` WHERE `nume` LIKE 'ion';
SELECT * FROM `elevi` WHERE `varsta` = 14;
SELECT * FROM `elevi` WHERE `varsta`!=12;
SELECT * FROM `elevi WHERE `nume` IS NOT NULL;

4.6 Modificarea informatiilor stocate intr-o tabela


O alta operatie importanta este cea de modificare a informatiilor existente intr-o tabela. Acest lucru
se poate face folosind instrctiunea UPDATE:

136

UPDATE <tabela> SET <coloana>=<valoare>, <coloana2>=<valoare> ... WHERE <coloana>


<operator> <valoare>;
Prin urmare modificam valorile anumitor atribute acelor inregistrari carora li se adresaeaza
instructiunea prin operatia descrisa dupa WHERE; Operatorii si operatiile posibile sunt similare
celor de la instructiunea SELECT prin care specificam anumite inregistrari in functie de atributrle
acestora;
Exemplu:
UPDATE `elevi` SET `nume`='George' WHERE `id`=1;
Operatiune se poate face in aplicatia phpmyadimin in urmatorul fel: Dupa selectarea inregistrarilor
dintr-o tabela in dreptul inregistrarii pe care dorim sa o modificam apasam iconita ce descrie un
creion;

137

Modificam valorile atributelor;

In cazul acesta am modificat numele in George;


138

Dupa modificare se observa ca la selectare atributul nume al primei inregistrari are valoarea George;

4.7 Stergerea informatiilor din tabele


Ultima operatie de baza cu care se poate lucra pe inregistrarile unei tabele este stergerea acestora
(inregistrarilor); Operatiunea de stergerea se face cu ajutorul instructiunii DELETE;
Instructiunea DELETE are urmatoarea sintaxa:
DELETE FROM <tabela> WHERE <coloana> = <valoare>;
Aceasta instructiune sterge inregistrarile din tabela precizata care respecta regula data de operatia de
dupa WHERE;
Exemple:
139

DELETE FROM `elevi` WHERE `id`=1;


DELETE FROM `elevi` WHERE `nume` LIKE 'George';
Stergera inregistrarilor folosind aplicatia phpMyAdmin se face folosind iconita sub forma unui X de
culoare rosie din dreptul inregistrarii pe care dorim sa o stergem:

140

141

Modulul 5: Java si conexiunea la baza de date

5.1 Intelegerea legaturii dintre Java si baze de date


Dupa cum am inteles din capitolele anterioare bazele de date reprezinta colectii de tabele ce
relationeaza. Aceste tabele relationare sunt create in scopul aranjarii datelor in vederea acesarii lor.
Practic SQL inseamna Structured Query Language (deci limbaj structurat de interogare). Serverul
SQL se ocupa de interpretarea instructiunilor invatate in modulele anterioare pentru a structura
informatia in tabelele definite de noi.
In continuare vom spune ca folosim Java pentru lucrul cu baze de date. PRECIZARE: Aveti in
vedre faptul ca nu limbajul de progrmare Java se ocupa de structurarea tabelelor si nici aplicatia pe
care o cream. In continuare serverul pe care l-am instalat pe computere sa va ocupa de acest aspect al
aplicatiei. Practic, programarea bazelor de date cu java inseamna nimic altceva decat trimiterea
instruxtiunilor SQL invatate prin intermediul aplicatiei catre server;
De ce avem nevoie sa cream o aplicatie care sa lucreze cu baze de date daca serverul se ocupa
de prelucrarea acestora?
Crearea unei aplicatii care lucreaza impreuna cu un server de baze de date poate fi - o simpla
aplicatie care functioneaza ca intergara grafica user-friendly (pentru ca alternativa la o astfel de
aplicatie ar fi monitorul MySQL - deci lucrul in consola cu serverul) pana la folosirea bazelor de date
pentru a stoca structurat in tabele informatia necesara unei aplicatii (informatia pe care o aplicatie o
proceseaza in vederea obtinerii unor rezultate utile care sunt afisate). Sa presupunem ca exemplu ca
avem de creat o aplicatie care inregistreaza produsele unui supermarket si incasarile acestuia
(vanzarile); Este usor de observat ca avem nevoie de o baza de date pentru a structura informatiile
repferitoare la produse si la vanzari.
JDBC - Java DataBase Conectivity
Exista mai multe tipuri de drivere pentru conectarea la o baza de date. Acestea sunt data in functie de
tipul de baza de data la care dorim sa ne conectam; Pot fi drivere JDBC:ODBC sau JDBC:MySQL ...
etc.
Driverul este cel care face legatura intre aplicatia creata de noi cu Java si serverul de baze de date. In
functie de serverul pe care il folosim (tipul de tehnologie folosit) vom avea nevoie de un anumit
driver. Daca dorim spre exemplu sa facem conexiunea cu o baza de date MySQL (cazul cursului
nostru) vom folosi driverul JDBC:MySQL; Pentru aceasta vom avea nevoie de pachetul
Connector/J. Acest pachet poate fi downloadat gratuit de pe site-ul MySQL (
http://www.mysql.com ); Adresa exacta este http://dev.mysql.com/downloads/connector/j/5.1.html ;
De la adresa data mai sus puteti downloada versiunea 5.1 a pachetului Connector/J. Va recomand
intotdeauna sa verificati care este ultima versiune aparuta si sa o downloadati. Nu este neaparat
nevoie si nici recomandat sa folositi versiunea 5.1. Odata cu trecerea timpului vor aparea din ce in ce
mai multe versiuni - recomandat este sa o folositi pe ultima;

142

Pentru a va usura munca in studiu puteti downloada versiunea 5.1.6 a Connector/J de pe urmatorul
link: download
Practic aplicatia noastra va functiona dupa schema:
APLICATIE <=> CONNECTOR/J <=> SERVER MySQL
Dupa downloadarea arhivei veti folosi din interioarul acesteia pentru crearea aplicatiei pachetul
mysql-connector-java-5.1.6-bin.jar
Pachetul mysql-connector-java-5.1.6-bin.jar va fi copiat in folderul specific proiectului NetBeans (de
obicei NetBeans salveaza proiectele in folderul My Documents/NetBeansProjects). Vom copia
aceasta arhiva jar in folderul proiectului pentru a nu modifica valoarea variabilei CLASSPATH.

AM creat proiectul SQL1; Pentru acest proiect am exemplificat modul in care am importat libraria
din pachetul mysql-connector-java-5.1.6-bin.jar

143

144

5.2 Crearea conexiunii cu serverul


Vom continua cu scrierea aplicatiei: Presupunem ca aveti instalat si pornit serverul MySQL (instalat
in modului 3 cu pachetul XAMPP)

Pasul 1: Incarcarea driverului JDBC


Acest lucru se face folosind apelul metodei forName() din clasa Class. Metoda este statica prin
urmare sintaxa este:
Class.forName("com.mysql.jdbc.Driver");

145

Este important sa tratam fiecare exceptie si sa afisam mesajele de eroare pentru a identifica usor
probeleme in cazul in care acestea apar. Daca nu afisam eroarile care pot fi aruncate va fi foarte greu
sa depanam aplicatia; Am folosit o structura try-catch in vederea tratarii exceptiilor ce pot aparea;
Pasul 2: Se creaza o baza de date

Voi folosi baza de date mydatabase deja existanta (am creat-o si folosit-o in modulele anterioare);
Puteti crea o baza de date noua in vederea construirii aplicatiei; Nu confundati baza de date cu tabela.
O baza de date poate avea una sau mai multe tabele ce relationeaza. In cazul meu tabela este elevi.
Pasul 3: Se creeaza o conexiune
Folosind metoda statica getConnection() din clasa DriverManager cream conexiunea cu serverul
MySQL; In fapt cream o conexiune directa la o baza de date creata ( mydatabase ).
Metoda getConnection() primeste trei parametri: o adresa (String), un user (String) si o parola
(String); Vom folosi userul root care default nu are parola setata;

146

Connection con = DriverManager.getConnection("jdbc:mysql://localhost/mydatabase",


"root", "");
Sintaxa adresei este: jdbc:mysql://adresa_server/nume_baza_de_date

5.3 Preluarea informatiilor din baza de date


Asa cum deja stim informatiile pot fi extrase din baza de date folosind instructiunea SELECT. Sa ne
amintim sintaxa pentru preluarea tuturor informatiilor:
SELECT * FROM <tabela>;
Vom contiuna aplicatia SQL1 din lectia anterioara presupunand ca vrem sa extragem toate
informatiile despre toti elevii inscrisi; Aveti in vedere inregistrarea catorva elevi in baza de date in
prealabil pentru a avea ce informatii sa preluati;
Dupa ce am construit conexiunea cu serverul urmeaza sa descriem pasii de urmat in vederea preluarii
informatiei dintr-o tabela:
Pasul 1: Crearea conexiunii
Statement s = con.createStatement();
Construim un obiect Statement si folosim metoda comportamen createStatement() pe instanta de
conexiune creata anterior (vezi lectia anterioara pentru con);
Pasul 2: Scriem o instructiune SELECT
String sql = "SELECT * FROM `elevi`";
Pasul 3: Preluam informatia din tabela intr-o structura ResultSet
ResultSet este o colectie in care noi putem stoca informatia extrasa din tabela;
ResultSet rs = s.executeQuery(sql);
executeQuery(String s) este metoda pe care o puteti folosi pentru trimiterea unei instructiuni
SELECT catre serverul cu care s-a facut conexiunea; Aceasta metoda returneaza dupa cum ati vazut
o instanta ResultSet;
Pasul 4: Parcurgerea colectiei si afisarea informatiei
Ne imaginam colectia ca fiind tabelul pe care il returneaza instructiunea SELECT data. In cazul meu
tabelul are sapte coloane si un numar de trei inregistrari (avem in vedere faptul ca in mod normal nu
cunoastram numarul de inregistrari);

147

Voi folosi o structura repetitiva while(){} pentru a parcurge randurile tabelului; Pentru ca nu stiu
numarul de inregistrari voi folosi sintaxa: while(rs.next()) {} care se traduce prin: "cat timp mai
exista un rand";
In interior voi folosi un for pentru a parcurge coloanele de la 1 la 7; (incepe cu 1 nu cu 0 ca la
tablouri):
while(rs.next()){
for(int i=1;i<7;i++) System.out.print(rs.getString(i)+" ");
System.out.println();
}
Metoda getString(int i) returneaza sirul de caractere specific unei anumite coloane; Am avut grija sa
afisez atributele elevilor cu spatii intre ele si fiecare inregistrare pe alt rand;

5.4 Referinta la coloane prin numele lor


In aplicatia anterioara am facut referire la campurile tabelei elevi prin identificatorul coloanei
colectiei ResultSet. Exista de asemenea posibilitatea de a face referire la atributele entitatii elev
direct prin numele acestora:

148

System.out.print(rs.getString("nume")+" ");
System.out.print(rs.getString("prenume")+" ");
System.out.print(rs.getString("varsta")+" ");
Metoda getString() ne ofera posibilitatea de a accesa valorile unori campuri folosind numele
campurilor respective: nume, prenume, varsta etc.

Observati sintaxa si resultatul obtinut la afisarea in consola;

5.5 Introducerea informatiilor in baza de date


Introducerea informatiilor in baza de date se face prin intermediul instructiunii INSERT; In exemplul
urmator am introdus un nou elev in baza de date folosind sintaxa MySQL:
"INSERT INTO `mydatabase`.`elevi` (`id`, `cnp`, `nume`, `prenume`, `scoala`, `varsta`)
VALUES (NULL, '183903429043', 'Florin', 'Vasile', 'Colegiul Mihai Viteazu', '17')";
Pasii pentru introducerea unei inregistrari intr-o tabela sunt asemanatori cu cei pentru vizualizare.
Totusi, este mai usor sa introducem date decat sa le vizualizam;
Pasul 1: Crearea instructiunii folosind clasa Statement
149

Statement s = con.createStatement();
Pasul 2: Scrierea instructiunii MySQL
String sql = "INSERT INTO `mydatabase`.`elevi` (`id`, `cnp`, `nume`, `prenume`, `scoala`,
`varsta`) " +
"VALUES " +
"(NULL, '183903429043', 'Florin', 'Vasile', 'Colegiul Mihai Viteazu', '17')";
Pasul 3: Executarea instructiunii:
s.executeUpdate(sql);
Observati ca de aceasta data am folosit metoda executeUpdate(); Aceasta nu returneaza un ResultSet
asa cum se intampla la folosirea metodei executeQuery();

150

5.6 Modificarea si stergerea informatiilor


Pentru a modifica o anumita inregistrare vom folosi instructiunea UPDATE; In urmatorul exercitiu
am modificat primei inregistrari numele in Ionut si prenumele in Popescu:
UPDATE `mydatabase`.`elevi` SET `nume` = 'Ionut',`prenume` = 'Popescu' WHERE
`elevi`.`id` =2
Vom folosi aceiasi pasi ca in cazul inserarii unei noi inregistrari:

151

Pentru stergerea unei inregistrari vom folosi instructiunea DELETE;


152

DELETE FROM `elevi` WHERE `id`=4;

153

5.7 Trimiterea grupurilor de interogari


Exista posibilitatea de a adauga mai multe interogari intr-o lista si apoi trimite intreaga lista catre
serverul de baze de date pentru a fi eecutata. In general intr-o lista nu sunt trimise interogari
SELECT. Adaugarea in lista se poate face folosind metoda addBatch(). Trimiterea listei catre
serverul de baze de date se poate face folosind metoda executeBatch(). Adaugarea intr-o lista a
interogarilor are un avantaj major: permite razgandirea utilizatorului inainte de trimiterea
interogarilor spre a fi executate. Stergerea interogarilor dintr-o lista poate fi facuta prin apelul
metodei clearBatch(); Metodele addBatch(), executeBatch() si clearBatch() sunt comportamente ale
interfetei Statement.

154

Dupa executie, daca raspunsul este Y sau y se poate verifica faptul ca cele doua interogari au fost
executate. In caz contrar va fi afisat un mesaj ca in imaginea de mai jos:

5.8 Crearea unei interfete grafice pentru afisare si stergere


Primul aspect referitor la o aplicatie cu interfta grafica care lucreaza cu un server de baze de date este
crearea conexiunii o singura data in clasa container: Main. In exemplul de mai jos o fereastra afisaza
intr-un tabel pe linii separate inregistrarile din tabela `persoane`. La apasarea pe un buton amplasat in
partea de jos a ferestrei stanga sunt sterse inregistrarile selectate.
Clasa Fereastra:

155

Constructorul trebuie sa primesca ca parametru instanta Statement. Folosind instanta Statement este
trimisa o interogare SELECT si este preluat un ResultSet. Instanta ResultSet este trimisa ca
parametru Clasei Model care defineste AbstractTableModel pentru tabelul creat si afisat pe fereastra:

La apasare pe buton sunt luate randurile selectate si folosind id-ul afisat in prima coloana sunt sterse
acele inregistrari. Prin apelul metodei refreshModel() definita mai jos este reactualizata modelul:
156

Afisarea se face efectiv in clasa Model care defineste interfata tabelului:


157

158

Apoi clasa Main creaza si afisaza o fereastra dupa ce realizeaza conexiunea cu serverul de baze de
date pornit local:

159

Rezultatul:

Dupa stergere:

160

161

5.9 Crearea unei interfete grafice pentru adaugare sau modificare


Pentru aplicatia din lectia anterioara, in lectia aceasta pe fereastra vom adauga meniul File cu
optiunile Adaugare si Modificare. La click pe optiunea Adaugare se va deschide o fereastra cu un
formular de adaugare a unei persoane in baza de date.
Primul pas este definirea global static in clasa a conexiunii, instantei Statement si frestrei principale:

In clasa Fereastra sunt definite instantele necesare construirii meniului:

162

La click pe optiunea de meniu Adaugare se creaza o instanta de FereastraAdaugare. Instanta primeste


ca parametru la construire si statement-ul pentru a putea trimite interogari catre baza de date.

163

Fereastra de adaugare are un formular format din doua componente text si un buton. La apasare pe
buton, folosind informatiile adaugate in componentele text este adaugata o noua inregistrare si
tabelul din fereastra principala este actualizat:

164

Rezultatul:

165

Similar poate fi creata o interfata pentru modificarea unei inregistrari:

166

Clasa FereastraModificare defineste fereastra folosita pentru modificarea instantelor:

167

168

169

170

Rezultatul:

Exercitii recapitulative pentru examen


1. Avand tabela Puncte ce stocheaza in baza de date coordonatele x si y prin care se pot defini
puncte pe un plan creati o aplicatie care citeste toaet punctele
din baza de date si:
- afisaza toate segmentele formate de puncte cu lungimea lor si le stocheaza in tabela Segmente
- afisaza toate triunghiurile definite de punctele stocate in tabela Puncte
BONUS: Se dau doua puncte sa se afiseze folosind baza de date segmente cel mai scurt drum intre
cele doua puncte date;
Observatii: se va lucra cu intrari si iesiri din consola
2. Creati un calculator care sa adune, sa scada, sa inmulteasca si sa afisele modulul a doua numere
complexe introduse. Creati o interfata grafica cu swing cat mai prietenoasa.
3. Creati un mini editor de text in care se pot scrie linii si salva documentul in format .txt; Creati o
interfata grafica cu swing prietenoasa;
4. Creati folosind interfata grafica swing jocul "Spanzuratoarea";
5. Creati folosind intrfata grafica swing jocul "Vaporase"

171

Modulul 7: Notiuni despre retele

7.1 Introducerea datelor in tabela prin interfata grafica


Vom incepe dezvoltarea aplicatiilor cu interfata grafica swing si conexiune cu o baza de date
MySQL prin crearea unui program care introduce date intr-o tabela. Datele vor fi introduse de
utilizator prin intermediul unei ferestre. Pentru aceasta aplicatie este necesar mai intai sa cream o
tabela pe care sa lucram. Tabela cu care deja ne-am obisnuit este Elevi, folosita anterior in aplicatiile
create la acest curs. Dupa ce vom crea intrfata grafica (prin mostenirea clasei JFrame) vom face
legatura cu baza de date la intalnirea unui eveniment. Cel mai des evenimentele vor fi de tip
ActionEvent (aruncate de instante JButton sau JMenuItem) dar in aceeasi maniera se poate crea in
aplicatie un comportament de conexiune cu o baza de date la intalnirea altor evenimente
(MouseEvent, MouseWheelEvent, KeyEvent, ItemEvent ... etc)
Incepem cu pornirea serverului de baza de date si a serverului Apache.

Creati un proiect nou in care vom incepe scrierea mai intai a clasei care mosteneeste JFrame si
descrie fereastra ce interactioneaza cu utilizatorul.

172

La crearea fiecarui proiect pentru aplicatii care lucreaza cu o baza de date nu uitati sa copiati
pachetul mysql-connector-java.jar in locatia proiectului dumneavoastra si apoi sa il importati ca
librarie prin NetBeans.

173

174

Verificati cu ajutorul phpMyAdmin daca exista baza de date si tabela. Daca acestea nu exista creatile si verificati in functie de numele pe care dumneavoastra la dati tabelelor si bazei de date sintaxa
corespunzatoare in crearea exercitiului.
In exemplul de mai jos tabela mea are campurile:
# id
o cnp
o nume
o prenume
o scoala
o varsta
Atentie. Nu confundati tabela cu baza de date. Baza de date are numele mydatabase si tabela are
numele elevi

175

Descrieti interfata ferestrei .Creati campuri pentru fiecare valoare care trebuie inserata. In exemplul
de mai jos am creat interfata folosind componente JLabel, componente JTextField (campurile text
pentru introducerea de informatie) si un buton la apasarea caruia se va introduce informatia in tabela.
De asemena aveti in vedere faptul ca nu am tratat toate exceptiile, decat cele care erau neaparat
necesare la conexiunea cu baza de date. Pentur dezvoltarea unei aplicatii profesionale, avand in
vedere cunostiinele voastre fundamentale incercati dupa finalizarea aplicatiei sa descoperiti ce alte
erori ar putea interveni ca urmare a incercarii inserarii unor valori necorespunzatoare si tratati aceste
exceptii.

176

177

Constructorul primeste ca paramentru titlul ferestrei si il seteaza cu ajutorul constructorului clasei


superioare (atentie, acest lucru se face numai pe prima linie a constructorului clasei curente).

178

Dupa setarea managerului de pozitionare si a componentelor urmeaza crearea unei instante in metoda
main pentru a observa interfata pe care am reusit sa o dezvoltam.

179

Metoda setResizable() este un comportament care poate primi ca parametru o valoare booleana. Daca
valoare este true atunci fereastra poate fi redimensionata, daca aceasta este false atunci ea nu poate
fi redimensionata.

180

7.2 Crearea conexiunii la aruncarea evenimentului


Atasam un ascultator butonului si suprascriem metoda actionPerformed; Practic aici se va face
conexiunea cu baza de date si tot aici vom si introduce informatia scrisa de utilizator in campurile
text create si atasate pe fereastra anterior.

Nu uitati ca pachetul java.sql trebuie importat pentru a putea lucra cu bazele de date MySQL.

181

Iata si respectarea catorva pasi pe care deja ii cunoasteti din lectia trecuta:
1. Incarcarea driverului
2. Crearea conexiunii
3. Preluarea informatiei care trebuie inserata si prelucrarea acesteia. Prelucrarea inseamna de fapt
adaugarea ghilimelelor simple de o parte si de alta a fiecarei informatii ce trebuie introdusa. Aceasta
regula face parte din limbajul MySQL (vezi capitolul ce se refera la sintaxa MySQL).
4. Crearea interogarii (Sirul cu comanda MySQL)
5. Crearea unei instante Statement pe baza conexiunii create anterior cu clasa Connection
6. Executarea interogarii prin metoda executeUpdate;

182

183

La sfarsit putetisterge continutul campurilor text dupa apsarea butonului si preluzarea informatiilor si
puteti desigur afisa exceptiile care pot fi intampinate in blocul try, prin apelarea metodei print in
blocul catch

184

Incercati aplicatia, verificati functionalitatea ei si daca aceasta nu functioneaza reluati pasii si gasiti
erorile.

7.3 Preluarea informatiilor din tabela


Pentru a vedea modul de crearea al unei aplicatii care lucreaza cu informatii existente intr-o baza de
date vom presupune urmatorul exercitiu:
Intr-o tabela numei puncte avem informatiile care definesc punctele pe un plan. Pe o componenta
JPanel va fi desenat drumul intre punctele inregistrate in tabela. Pentru acest lucru va trebui sa
extragem informatia din tabela puncte si sa o folosim pentru a crea obiecte in aplicatia Java.
Vom defini de asemenea obiectul Punct care sa corespunda inregistrarilor din tabele.

185

Aplicatia are un panou amplasat in partea centrala a ferestrei si un buton cu eticheta "Deseneaza"
amplasat in partea de jos a ferestrei.

186

Pasii de creare a conexiunii sunt similari celor de la introducerea informatiilor, doar ca, de aceasta
data va trebui sa si retinem informatia trimisa de server dupa executarea interogarii SELECT. vom
retine informatia intr-o colectie ResultSet.
Metoda pentru executarea interogarilor select este executeQuery.

187

Urmeaza acum sa cream clasa Punct, apoi vom parcurge colectia pentru a stoca toate punctele intrun vector de puncte. Acesta va fi folosit ulterior pentru desenarea drumului pe interfata panoului.

7.4 Crearea obiectelor raportat la entitatile bazei de date


Nu crearea clasei Punct este problema de inteles ci faptul ca in general oricare entitate se creaza la
design-ul bazei de date devine un obiect atunci cand trebuie extras ca informatie cu care urmeaza sa
lucram.Prin urmare daca urmeaza sa lucram cu puncte va trebui sa cream obiectul Punct care sa
corespunda inregistrarii din tabela puncte. In cazul exercitiului nostru obiectul este simplu de creat.
Acesta este definit de coordonatele x si y si de un nume dat punctului.
Obiectele pot fi, dupa caz, encapsulate daca aplicatia cere o mai mare securitate a atributelor
obiectului.

188

7.5 Parcurgerea colectiei si efectuarea algoritmului


Am introdus mai intai trei inregistrari in tabela.

189

Am parcurs folosind o structura repetitiva while(){} colectia si am creat pentru fiecare inregistrare un
obiect Punct intr-un vector.

Dupa aceasta am parcurs vectorul si am desenat pe interfata panoului prin suprascrierea metodei
paint

190

Rezultatul este deci drumul dintre punctele A si C prin punctul B;

191

Modulul 8: Pachetul java.net

8.1 Stergerea inregistrarilor din tabela


Intotdeauna cand ne gandim la stergerea inregistrarilor dintr-o tabela avem nevoie de o conditie in
urma careia sa verificam ce inregistrare stergem din tabela. De exemplu putem sterge o inregistrare
unde valoarea unui camp este egala cu ceva anume sau este asemanatoare cu ceva anume.
Interfata pe care o propun de aceasta data este foarte simpla, un camp de text si un buton, la apasarea
caruia se va sterge inregistrarea punct al carei atribut nume este cel dat in campul textfield de pe
interfata.

Folosim aceeasi pasi pe care i-am invatat la introducerea inregistrarilor, dar vom schimba sintaxa
MySQL cu instructiunea DELETE.

192

193

194

8.2 Modificarea inregistrarilor din tabela


Vom incerca sa cream o fereastra cu ajutorul careia sa preluam datele de care avem neovie pentru a
modifica o inregistrare. In mare avem nevoie de doua tipuri de date importante pentru a modifica o
inregistrare: 1. cu ce se modifica inregistrarea; 2. valoarea dupa care cream conditia de modificare;
Voi crea urmatoarea fereastra astfel incat sa preia prin intermediul campurilor text valorile ce sa
modifica si voi modifica inregistrarea dupa numarul de identificare (campul id) dat de utilizator.

195

196

197

8.3 Tratarea evenimantului si modificarea propriu-zisa


La scrierea metodei actionPerformed vom trata modificarea in functie de valorile campurilor text
introduse de utilizator. Observati modul in care am preluat informatia din componentele text in
variabile separate si le-am pregatit pentru scrierea sintaxei MySQL (Am incadrat fiecare valoare
intre ghilimele simple pentru a fi mai usor de vizualizat sintaxa la scrierea interogarii)

198

Incercam aplicatia si verificam daca s-au facut sau nu modificari in tabela puncte.

199

8.4 Tratarea exceptiilor


Considerand tratarea exceptiilor ca facand parte din notiunile fundamentale de Java nu am tratat
nicio exceptie in nicunul din cazurile pe care le-am dezvoltat ca exemple pentru dezvoltarea
aplicatiilor care lucreaza cu baze de date. De exemplu numai in ultima aplicatie as fi avut de tratat
cel putin cazul in care identificatorul introdus de utilizator in ultimul camp nu este un numar sau nu
exista in tabela puncte.
Orice exceptie trebuie tratata in cazul in care se lucreaza la aplicatii ce urmeaza cu adevarat a fi
folosite de utilizatori. Nu uitati de cele doua metode pe care le avem pentru tratarea unei exceptii
throws si try-catch-finally. Avand in vedere faptul ca la crearea conexiunii suntem oricum obligati
sa tratam exceptia cu un try-catch putem sa folosim aceste blocuri si pentru tratarea celorlalte
execeptii. Nu putem folosi throws atunci cand suprascriem (override) metode decat daca acestea au
fost declarate in clasa superioarasa trateze respectivele exceptii. De exemplu in cazul lui
actionPerformed nu putem sa folosim metoda throws. Daca doriti totusi sa folositi aceasta metoda
de tratare a exceptiilor atunci va recomand sa creati o metoda diferita care trateaza exceptiile cu
throws si apoi sa apelati aceasta metoda in actionPerformed.

200

8.5 Conexiunea cu mai multi clienti


Avand un fir separat de executie pentru client este foarte usor de tratat conexiunea unui server cu mai
multi clienti simultan. Trebuie creata o instanta de fir de executie si pornita pentru fiecare client.
Acest lucru se face prin apelul intr-un clclu infinit al metodei accept() si trimiterea valorii returnate
ca parametru constructorului clasei ServerThread.

Afisand un mesaj dupa fiecare client care reuseste conexiunea se poate observa ca este posibil pentru
mai multi clienti sa se conecteze la server:

201

8.6 Interfete grafice


Serverul este o aplicatie care ofera servicii clientilor. Aplicatia server nu are nevoie in cele mai multe
cazuri de o interfata grafica. Totusi, in functie de aplicatie, clientul dispune de o interfata grafica
specifica. In exemplul de mai jos, clientul reprezinta o aplicatie de conferinta IM. Un client trimite
catre server un mesaj, iar serverul redirecteaza mesajul catre ceilalti clienti conectati:

202

Clasa ServerThread trateaza pe server fiecare conexiune individual si independent:

203

Clientul are o fereastra principala in care poate scrie un mesaj pe care il trimite catre toti ceilalti
clienti conectati:

204

205

Dupa pornirea serverului fiecare client poate comunica cu toti ceilalti:

206

Modulul 9: Transferul instantelor

9.1 Intelegerea retelelor


Retelele de sisteme (computare, telefoane mobile, PDA-uri ... etc) presupun cunoasterea si
intelegerea de notiuni complexe si chiar algoritmi si metode matematice. Nu am pretentia de a
prezenta in detaliu modul in care functioneaza retelele ci doar de a prezenta notiunile esentiale intr-o
forma generala pentru a putea mai departe intelege modul in care functioneaza aplicatiile pe care le
vom crea. Scopul nostru este sa invatam sa cream programe care sunt executate pe masini ( sisteme )
diferite, dar care comunica intre ele prin fluxuri de informatie. Pentru intelegerea in detaliu a
notiunilor fundamentale despre retele recomand cursul CCNA 1: Networking Fundamentals, curs
care descrie in detaliu protocoalele si regulile de comunicare intre computere si alte sisteme.
Sa incepem de la o intrebare de baza care ar fi: Ce reprezinta o retea de sisteme?
O retea reprezinta interconectarea prin diferite medii fizice a doua sau mai multe computere pentru a
putea comunica dupa anumite protocoale sau reguli. Un exemplu comun de retea de sisteme ar fi o
retea de computere. Conectarea a doua sau mai multe computere reprezinta o retea de sisteme.
Exista trei medii fizice prin care mai multe computere spre exemplu pot fi conectate pentru a forma o
retea: cabluri de cupru, fibra optica sau mediul wireless (presupunand unde radio)
Conectarea fizica totusi nu este suficienta pentru ca sistemele sa poata transfera informatia de la unul
la celalalt. Pentru ca acest lucru sa fie posibil ele trebuie sa vorbeasca o limba comuna. Aceasta
limba comuna o reprezinta totalitatea regulilor pe care sistemele trebuie sa le respecte pentru a se
putea intelege intre ele. Este un fel de gramatica ( ceva mai matematica ) a computerelor. Aceste
reguli se numesc protocoale si sunt structurate pe mai multe nivele ce formeaza o stiva
(nivele/straturi = layers ):
7 Application
6 Presentation
5 Session
4 Transport
3 Network
2 Data Link
1 Physical
Cele mai importante protocoale pentru noi sunt situate pe layerele Application, Transport si
Network;
Layerul 3 - Network este cel ce defineste protocolul IP. Protocolul IP descrie adresa unica la nivel
global prin care poate comunica un sistem cu alte sisteme din afara retelei locale. Acesta adresa pe
32 de biti (4 bytes) este cea care denumeste un sistem;
Layerul 4 - Transport defineste conexiunea end-to-end intre sisteme. Pe acest layer sunt situate
protocoalele TCP si UDP, protocoale care descriu conexiunea si modul in care se transfera
informatia (orientat sau neorientat), dar mai important pentru noi (programatorii) este adresa pe care
207

layerul Transport o aloca. Aceasta se numeste port si reprezinta un numar ce denumeste procesul
care comunica in retea. Exista doua tipuri importante de porturi cu care ne vom intalni in dezvoltarea
programelor: porturi bine-cunoscute (well-known) si alte tipuri de porturi;

Porturile well-known sunt cele care descriu protocoale definite prin standarde internationale cum ar
fi spre exemplu HTTP, FTP, SMTP, IMAP, POP3...etc. Pe acestea le vom folosi atunci cand vom
avea nevoie de unul dintre aceste protocoale binecunoscute;
Porturile well-known sunt numere intre 0 si 1023.
Exemplu:
80 HTTP
25 SMTP
110 POP3
22 SSH
20, 21 FTP
etc...
Pentru a dezvolta alte tipuri de procese vom folosi numere mai mari de 1023 si pana in 65535.
Adresa IP impreuna cu portul se noteaza sub forma IP:PORT si se numeste Socket. Exemplu:
192.168.1.200:80 sau localhost:1234
Socketul este adresa de care o aplicatie are nevoie pentru a forma o conexiune. Trebuie sa existe un
Socket pe fiecare dintre participantii la comunicare.
O alta notiune esentiala este "ip de loopback" - Se numeste ip de loopback adresa 127.0.0.1 denumita
si standard localhost pentru orice sistem. Este adresa care face referire la sistemul local. Aceasta
adresa este importata pentru ca in majoritatea exemplelor voi folosi localhost sau 127.0.0.1, deoarece
aplicatiile care comunica se vor afla ambele pe acelas computer (cel pe care construiesc exemplul);

9.2 Dezvoltarea unui exemplu de aplicatie server


Ce inseamna apliatie server?
Aplicatia server este acel tip de aplicatie care ofera un anumit tip de serviciu. Serviciile sunt oferite
aplicatiilor denumite aplicatii client. Practic o aplicatie server primeste o anumita informatie de la
unul sau mai multi clienti, o proceseaza apoi trimite un raspuns clientului inapoi.
O aplicatie server intotdeauna asteapta conectarea unui client. Prin urmare o astfel de aplicatie nu
lucreaza fara a avea cu cine sa lucreze.
Pentru inceput vom crea o aplicatie server al carei tip poate o sa vi se para inutil. Asa si este, dar este
pasul cel mai important pentru ca mai departe pe acelasi principiu sa dezvoltam aplicatii mult mai
208

complexe. Iata despre ce este vorba. Vom crea o aplicatie server la care nu se poate conecta decat
maximum un client o singura data. Clientul va trimite o informatie si serveul o va procesa intr-un
anumit fel apoi va da un raspuns clientului. Ce este foarte primitiv la aceasta aplicatie este faptul ca
ea nu poate sa raspunda decat cerintelor unui singur client odata. Bineinteles, nicio aplicatie server
nu este utila decat atunci cand poate fi accesata de un numar mare de clienti pentru ca altmiteri am
prefera sa cream o singura aplicatie care sa proceseze informatia, nu doua.
Iata ce vom face ca exemplu: Serverul despre care vorbeam va primi un sir de caractere si il va
inversa folosind metoda reverse din clasa StringBuffer. Apoi va trimite clientului sirul inversat.

Dupa crearea unui proiect voi crea separat o clasa Server. Aceasta contine metoda principala main(),
deoarece, ne amntim, Serverul este o aplicatie independenta. Pentru inceput vom importa pachetele
necesare:
java.net - contine clasa ServerSocket si clasa Socket; Sa discutam cate ceva despre aceste doua clase;
Clasa Socket este cea care descrie o instanta Socket - instanta ce reprezinta un capat de conexiune.
Pentru a crea o conexiune avem nevoie de doua Socket-uri, unul ce reprezinta procesul serverului iar
celalat ce reprezinta procesul clientului. Cu alte cuvinte avem doua capete de conexiune intre care
formam o conducta de transfer a informatiei. Putem compara conexiunea cu o conducta prin care
curge informatia in doua sensuri: de la server la client si viceversa;

209

Clasa ServerSocket este cea cu ajutorul careia noi construim capatul conexiunii (Socket-ul) pentru
server. In momentul in care capatul conexiunii pe server se formeaza se creeaza practic intraga
conducta de comunicare, dar pentru ca noi nu stim pe ce sistem se afla aplicatia care urmeaza sa se
conecteze si prin urmare nu stim informatii despre acesta (cum ar fi ip-ul lui) nu putem crea in mod
direct un Socket. In acest caz folosim o instanta ServerSocket si metoda accept() care intrerupe firul
de executie al aplicatiei si asteapta pana la conectarea unui client, pentru a putea prelua informatiile
de la acesta necesarea pentru crearea conexiunii.

java.io - Contine clasele cu ajutorul carora vom crea fluxurile de informatii pe conducta creata intre
doua socketuri;

210

Neaparat vom trata exceptiile care ar putea sa apara din cauza imposibilitatii de conectare intre cele
doua sisteme.

211

Instanta ServerSocket are ca atribut principal portul pe care definim functionalitatea serverului.
Acest port trebuie sa aiba o valoare intre 1023 ssi 65535, adica nu una dintre valorile unui port wellknown; Dupa crearea instantei de ServerSocket apelam metoda accept() care intrerupe firul de
executie si asteapta returnarea unui Socket la conexiunea cu un client. Returnarea Socket-ului este
echivalenta cu crearea conductei de comunicare.

212

Dupa ce suntem siguri ca avem o comunicare putem defini fluxurile de intrari si de iesire prin acea
conducta creata intre cele doua socketuri. Facem acest lucru folosind clasele BuffereReader si
PrintWriter.
Metodele getOutputStream() si getInputStream() sunc comportamente ale unui Socket si ne ajuta sa
preluam practic fluxurile de la capatul unei conexiuni.

213

Algoritmul este simplu. Tot timpul ( while(true) ) serverul asteapta un sir de caracter de la client apoi
in momentul in care se primeste acesta il inverseaza si trimite inapoi sirul de caractere inversat. Dupa
ce isi trimna treaba ciclul revine la prima instructiune unde se astepata din nou un sir de caractere de
la client.

9.3 Dezvoltarea unui exemplu de aplicatie client


Ce inseamna apliatie client?
Aplicatia client este cea care beneficiaza de serviciile unui server. Aceasta trimite informatie si
primeste raspunsul aplicatiei server ce reprezinta informaia trimisa procesata.

214

Ne amintim ca si aplicatia Client este o aplicatie independenta. Cu alte cuvinte contine o metoda
main() de la care incepe executia aplicatiei. Algoritmul este simplu: Aplicatia trebuie sa trimita un sir
introdus de utilizator de la tastatura si sa afiseze pe ecran (in consola) informatia primita de la
serverul dezvotlat in lectia anterioara;
215

216

Pasii sunt asemanatori, doar ca de aceasta data putem crea direct un Socket pentru ca un client
trebuie sa stie cu exactitate care este IP-ul si care este port-ul pe care se conecteaza. In cazul meu am
dat ca parametii "localhost", pentru ca voi porni serverul pe aclas omputer pe care creez si exemplul
de client si portul 4321 pe care i-am precizat mai devreme serverului ca trebuie sa asculte.
Clasa Socket primeste ca parametii la construirea instantei adresa serverului sub forma de obiect
String si portul pe care clientul se conecteaza. Adresa poate fi un nume sau o adresa IP.

Pe baza Socket-ului construim fluxurile de intrare si de iesire la conexiunea creata si cream si un flux
pentru citirea din consola (de la tastatura). Am preferat in acest exemplu sa ciresc de la tastatura
folosind tot clasa BufferedReader. Puteti totusi folosi o alta metoda daca considerati.

217

Intr-un ciclu while care teoretic repata instructiunile la infinit citesc un sir de caractere de la
tastatura, il trimit catre server, apoi preiau mesajul serverului si afisez pe ecran ce a trimis acesta.

218

Pentru ca ciclul wile sa poata fi intrerup pot sa conditionez acest lucru de exemplu prin valoarea
sirului introdus de utilizator, daca acesta este "papa" atunci se executa o instructiune break care
intrerupe ciclul si incheie executia aplicatiei.

9.4 Testarea aplicatiilor


Testarea aplicatiilor create presupune pornirea celor doua programe, dar atentie, mai intai porniti
serverul .Pentru ca un client sa aiba unde sa se conecteze mai intai serverul trebuie sa fie pornit si sa
astepte conectarea unui client. Apoi. in momentul in care aplicatia client este pornita serverul trece
de instructiunea accept() si astepta sa primeasca un si de caractere;
In acelas timp pe client vi se cere introducerea unui sir de caractere. La introducerea sirului apoape
instantaneu veti vedea pe ecran sirul inversat.
Practic sirul a ajuns la server, care l-a inversat si la trimis inapoi. Clientul a primit sirul inversat si l-a
afisat pe ecran.

219

In exemplul de mai sus se vede cum eu am introdus sirul "Un mesaj" si am primit acelas sir inversat;

220

Modulul 10: Folosirea pachetului javax.mail

10.1 Functionalitatea serverului de email


Serverul de email din punctul de vedere al clientului este sistemul care ii permite sa trimita si sa
receptioneze mesaje de email. Trimiterea si receptionarea se face prin intermediul unei aplicatii
numite client mail (Ex: Outlook, Mozilla Thunderbird ... etc) care se poate conecta la server,
comunica cu acesta si schimba informatie care este trimisa sau ceruta de utilizator. De fapt, ca
programatori vom considera separate operatiunile de trimitere sau receptionare, cele doua fiind
tratate de servere diferite ce functioneaza prin folosirea de protocoale diferite.
Protocoalele folosite de serverele mail sunt:

SMTP (Simple Mail Transfer Protocol) - pentru trimiterea mesajelor


POP3 (Post Office Protocol 3) - pentru receptionarea mesajelor
IMAP (Internet Message Access Protocol) - pentru receptionarea mesajelor

Prin urmare, pentru trimiterea unui mesaj de SMTP este necesar un sever care sa realizeze
operatiunea, iar pentru receptionarea unui mesaj este necesar un server POP3 sau IMAP. Pentru acest
curs am sa folosesc telacad.ro ca server SMTP si POP3.

10.2 Trimiterea unui mail cu Java


Pentru a crea o aplicatie din care se poate trimite un mesaj email este necesar pachetul javax.mail,
care contine clasele ce definesc comportamente necesare conexiunii cu serverul SMTP si trimiterii
informatiei catre acesta. Exemplul de mai jos trimite un mesaj de test catre serverul SMTP, care va
trimite mai departe mesajul catre adresa de email: test@telacad.ro .
221

222

Exemplul de mai sus este cel mai simplu exemplu de trimitere a unui mesaj de email printr-un server
SMTP. Este posibil insa ca serverul sa nu permita trimiterea prin configurari implicite. De exemplu
serverul nu foloseste portul implicit 25 pentru SMTP. In cazul in care se doreste modificarea
configurarilor implicite prin care este trimis mesajul este necesara modificarea proprietatilor din
antetul mesajului. Iata cele mai utile proprietati ale caror valori pot fi modificate:

223

Proprietate

Semnificatie

mail.from

adresa folosita pentru reply de destinatar

mail.host

numele serverului mail folosit

mail.user

user-ul specificat serverului de mail

mail.<protocol>.host

adresa serverului de mail folosita la trimitere

mail.<protocol>.port

portul folosit la trimiterea mesajului (in cazul in care serverul nu


foloseste portul implicit)

mail.<protocol>.user

userul cu care se identifica expeditorul pe server

mail.<protocol>.password

parola cu care se identifica expeditorul pe server

In tabelul de mai sus <protocol> trebuie inlocuit cu protocolul folosit. De exemplu la trimitere este
smtp

224

In concluzie pasii care trebuie urmati pentru trimiterea unui mesaj de email sunt:
1.
2.
3.
4.

setarea proprietatilor (antetul mesajului)


setarea adreselor de trimitere
setarea subiectului si a continutului
trimiterea mesajului

10.3 Trimiterea unui mail formatat HTML


Un mesaj poate fi trimis in CC sau BCC similar modului in care este trimis in recipient TO:

225

Daca se incearca in exemplul de mai sus formatarea cu HTML rezultatul nu va fi cel asteptat:

226

Cu cateva modifiari aduse codului, mesajul va fi interpretat in format HTML:

227

10.4 Atasamente
Exista posibilitatea de a trimite atasamente in mesajul de email. Aplicatia de mai jos deschide o
fereastra si lasa posibilitatea utilizatorului de a trimite mesaje prin intermediul unui server la care
acesta poate adauga si un fisier ca atasament:
Clasa Email are ca atribute toate piesele necesare pentru formarea mesajului care sa poata fi trimis.
Constructorul clasei defineste un mesaj, iar comportamentul sendEmail() este folosit pentru
trimiterea mesajului.

228

Metoda sendEmail() trimite mesajul pe baza informatilor setate. Deoarece mesajul va avea si un
fisier atasat acesta va fi compus din doua parti... mesajul si atasamentul:

229

Metosa getContentType() trebuie suprascrisa pentru a returna tipul de flux corespunzator (formatul
folosit). In acest caz "application/octet-stream"

Dupa adaugarea partilor la mesaj acesta poate fi trimis:

230

Clasa Fereastra:

231

232

Clasa Main :

233

Rezultatul:

234

235

236

10.5 Receptionare mesaje email cu POP3


In exemplul de mai jos este prezentata modalitatea de citire a mesajelor dintr-un folder din sistemul
de fisiere alocat de serverul de email prin folosirea protocolului POP3 :
Pentru receptionare de mesaje este necesara existenta unui user si a unei parole. In exemplu este
folosita adresa de email de test care are utilizatorul setat: test@telacad.ro si parola 12345.

237

Dupa trimiterea unui mesaj spre aceasta adresa, mesajul apare in consola, acesta fiind afisat in
intregime cu tot cu antete.

238