Differences

This shows you the differences between two versions of the page.

Link to this comparison view

poo:breviare:breviar-10 [2018/11/27 15:52]
matei.teodorescu
poo:breviare:breviar-10 [2025/11/30 17:37] (current)
george.tudor1906
Line 1: Line 1:
-====== Breviar ====== +====== Breviar ​10 ======
-===== Laborator 10 - Interfete ​=====+
  
-  * Responsabil:​ [[mihai.nan.cti@gmail.com|Mihai Nan]] +=== Interfețe grafice - Componente avansate ===
-  * Profesor titular: Carmen Odubășteanu+
  
-==== Introducere ====+=== 1. Liste de selecție ​===
  
-In cazul programelor pe care le-am facut pana acum, toate mesajele si raspunsurile apareau ca linii de text sugestive, ecranul fiind folosit in mod text. Un astfel de stil de comunicare nu este atractiv pentru utilizatori,​ motiv pentru care se prefera dialogul prin interfete grafice sau **//GUI (Graphical User Interface)//​**,​ ecranul fiind folosit in mod grafic.+== 1.1 Introducere ==
  
-In trecerea ​de la o versiune la alta, bibliotecile ​de clase care ofera servicii grafice au suferitprobabil, cele mai mari schimbari. Acest lucru se datoreazape de o parte, dificultatii legate de implementarea notiunii de portabilitate,​ iar pe de alta parte nevoii ​de a integra mecanismele GUI cu tehnologii aparute si dezvoltate ulterior.+Un obiect ​de tip **JList** prezintă utilizatorului un grup de item-uriafișate în una sau mai multe coloanepentru a oferi acestuia posibilitatea ​de a alege.
  
-In momentul actual, exista doua modalitati de a crea o aplicatie cu interfata grafica, iar acestea sunt: +== 1.2 Crearea unui model ==
-    * **//AWT (Abstract Windowing Toolkit)//​** - este API-ul initial pus la dispozitie incepand cu primele versiuni de Java; +
-    * **//​Swing//​** - este parte dintr-un proiect mai amplu numit **//JFC (Java Foundation Classes)//​** creat in urma colaborarii dintre Sun, Netscape si IBM, care se bazeaza pe modelul **//​AWT//​**,​ extinzand functionalitatea acestuia si adaugand sau inlocuind unele componente pentru dezvoltarea aplicatiilor GUI.+
  
-<note warning>​ +Există trei metode prin care se poate crea un model de listă:
-Este preferabil ca aplicatiile Java sa fie create folosind tehnologia Swing, deoarece aceasta pune la dispozitie o paleta mult mai larga de facilitati, insa nu se va renunta complet la AWT, deoarece aici exista clase esentiale, reutilizate in Swing. +
-</​note>​+
  
-==== Pachetul Swing ====+  * **DefaultListModel** - aproape totul este gestionat de model pentru a ușura munca programatorului;​ 
 +  * **AbstractListModel** - utilizatorul gestionează datele și invocă metodele de acționare. Pentru această abordare, programatorul trebuie să subclaseze **AbstractListModel** și să implementeze metodele //​getSize()//​ și //​getElementAt()//​ moștenite din interfața **ListModel**;​ 
 +  * **ListModel** - utilizatorul gestionează totul.
  
-Componentele **//​Swing//​**,​ spre deosebire de predecesoarele din versiunile Java anterioare, sunt implementate in intregime in Java. Aceasta are ca rezultat o mai buna compatibilitate cu platforme diferite decat in cazul folosirii componentelor **//​AWT//​**. Unul din principalele deziderate ale tehnologiei **//​Swing//​** a fost sa puna la dispozitie un set de componente GUI extensibile care sa permita dezvoltarea rapida de aplicatii Java cu interfata grafica competitiva,​ din punct de vedere comercial. Cel mai important pachet, care contine componentele de baza este **//​javax.swing//​**.+== 1.3 Inițializarea unei liste ==
  
-Orice interfata utilizator Java este compusa din urmatoarele elemente: +Iată un exemplu de cod care creează și setează parametrii unei liste:
-    * **//​Componente//​** – orice poate fi plasat pe o interfata utilizator, cum ar fi //​butoane//,​ //liste de derulare//, //meniuri pop-up//, //casete de validare// sau //campuri de text//; +
-    * **//​Containere//​** – acestea reprezinta componente care pot conţine alte com- ponente (de exemplu ​//​panouri//,​ //​casete ​de dialog// sau //ferestre independente//​);​ +
-    * **//​Administratori de dispunere//​** – reprezinta obiecte ​care definesc modul in care sunt aranjate (dispuse) componentele intr-un container. Admin- istratorul de dispunere nu este vizibil intr-o interfata, insa sunt vizibile rezultatele ”muncii” sale. Dispunerea componentelor interfetei este de mai multe feluridispunere secventiala,​ dispunere tabelara, dispunere marginala sau dispunere tabelara neproportionala.+
  
-=== Crearea ferestrelor ===+<code java> 
 +list new JList(data);​ // data e de tipul Object[] 
 +list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);​ 
 +list.setLayoutOrientation(JList.HORIZONTAL_WRAP);​ 
 +list.setVisibleRowCount(-1);​ 
 +// ... 
 +JScrollPane listScroller ​new JScrollPane(list);​ 
 +listScroller.setPreferredSize(new Dimension(250,​ 80)); 
 +</​code>​
  
-Clasa **//JFrame//** este cea pe care o vom folosi pentru a crea ferestre. Ca orice alta clasa care reprezinta componente ​**//Swing//** ea se afla in pachetul ​**//​javax.swing//​**. Pentru ca este un container, vom folosi, de cele mai multe ori, aceasta clasa prin mostenire nu prin instantiere. Altfel spus, vom crea clase care sa reprezinta ferestre si pentru ca acestea sa devina ferestre ​de tip **//JFrame//** ele vor mosteni aceasta clasa.+Alți constructori pentru ​**JList** permit inițializarea listei dintr-un obiect de tip **Vector** sau dintr-un obiect de tipul **ListModel**. Dacă inițializarea se face dintr-un obiect ​de tip **Vector** sau dintr-un vector clasic intrinsec, constructorul implicit creează un model standard de listă.
  
-<code java>+<note important>​ 
 +Modelul standard este imutabil - nu se pot adăuga, șterge, înlocui intrări în listă. Pentru a crea o listă a cărei intrări pot fi modificate individual, se poate seta modelul listei către o instanță variabilă, cum ar fi **DefaultListModel**. Modelul unei liste se poate seta când se creează lista sau prin apelul metodei //​setModel()//​. 
 +</note>
  
-public class Fereastra extends JFrame { +Apelul //​setSelectionMode()//​ specifică câte intrări din listă poate selecta utilizatorul și dacă acestea trebuie să fie sau nu continue.
-    private JButton button;+
  
-    public Fereastra ​(String text)+Apelul //​setLayoutOrientation()// permite afișarea datelor în mai multe coloaneValoarea **JList.HORIZONTAL_WRAP** specifică faptul că lista ar trebui să își afișeze intrările de la stânga la dreapta înainte de a trece la o nouă linie. O altă valoare posibilă este **JList.VERTICAL_WRAP**care specifică afișarea datelor de sus până jos (ca de obiceiînainte de a trece la o coloană nouă.
-        super(text);​ +
-        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);​ +
-        setMinimumSize(new Dimension (3 0 02 0 0)); +
-        getContentPane().setBackground (Color.blue);​ +
-        setLayout(new SpringLayout());​ +
-        button = new JButton("​Apasa"​);​ +
-        add(button);​ +
-        show(); +
-        pack(); +
-   }+
  
-    ​public ​static ​void main(String args[]) { +<note tip> 
-        ​Fereastra f new Fereastra("​Laborator POO" ​) ;+În combinație cu apelul //​setLayoutOrientation()//,​ invocarea metodei //​setVisibleRowCount(-1)//​ oferă listei posibilitatea de afișare a numărului maxim de intrări cuprins în spațiul disponibil pe ecran. O altă utilizare pentru //​setVisibleRowCount()//​ este aceea de a indica panoului de scroll-ing asociat listei câte rânduri să afișeze. 
 +</​note>​ 
 + 
 +== 1.4 Selectarea intrărilor dintr-o listă == 
 + 
 +O listă utilizează o instanță de **ListSelectionModel** pentru a-și gestiona selecția. Implicit, modelul de selecție a unei liste permite selecția oricărei combinații de intrări la un moment dat. Se poate specifica un mod diferit de selecție prin apelul metodei //​setSelectionMode()//:​ 
 + 
 +  * **SINGLE_SELECTION** - numai o singură intrare poate fi selectată la un moment dat. Când utilizatorul selectează o intrare, orice intrare anterior aleasă este deselectată;​ 
 +  * **SINGLE_INTERVAL_SELECTION** - intrări multiple și continue pot fi selectate. Când utilizatorul începe un nou interval de selecție, orice intrări anterior alese sunt deselectate;​ 
 +  * **MULTIPLE_INTERVAL_SELECTION** - mod implicit. 
 + 
 +<note important>​ 
 +Indiferent de modelul de selecție folosit de listă, aceasta generează evenimente de selecție de fiecare dată când selecția se schimbă. Aceste evenimente pot fi procesate prin adăugarea unui ascultător la listă folosind metoda //​addListSelectionListener()//​. Acest ascultător trebuie să implementeze o metodă: //​valueChanged()//​. 
 +</​note>​ 
 + 
 +<code java> 
 +public void valueChanged(ListSelectionEvent e) { 
 +    if (e.getValueIsAdjusting() == false) { 
 +        ​if (list.getSelectedIndex() ​== -1) { 
 +            fireButton.setEnabled(false); 
 +        } else { 
 +            fireButton.setEnabled(true);​ 
 +        }
     }     }
 } }
 +</​code>​
  
 +Multe evenimente de selecție pot fi generate de o singură acțiune a utilizatorului,​ cum ar fi un click. Metoda //​getValuesAdjusting()//​ returnează //true// dacă utilizatorul încă manipulează selecția. Programul de mai sus este interesat doar de rezultatul final al acțiunii utilizatorului și, de aceea, metoda //​valueChanged()//​ conține secvența de cod doar dacă //​getValuesAdjusting()//​ întoarce //false//.
 +
 +Deoarece lista este în modul **SINGLE_SELECTION**,​ acest cod poate utiliza metoda //​getSelectedIndex()//​ pentru a obține indexul intrării tocmai selectate. **JList** pune la dispoziție și alte metode pentru a seta sau a obține selecția când se pot alege mai multe intrări. De asemenea, se pot asculta evenimente direct pe modelul de selecție, dacă acest lucru este dorit.
 +
 +== 1.5 Adăugarea și ștergerea ==
 +
 +<code java>
 +listModel = new DefaultListModel();​
 +listModel.addElement("​Debbie Scott"​);​
 +listModel.addElement("​Scott Hommel"​);​
 +listModel.addElement("​Alan Sommerer"​);​
 +list = new JList(listModel);​
 </​code>​ </​code>​
  
-Metoda ​**//​add(Component c)//** este folosita pentru a adauga pe fereastra o componenta exact ca in cazul AppleturilorMetoda ​**//add()//** este mostenita ​din clasa **//​Container.//**+Programul de mai sus utilizează o instanță ​**DefaultListModel**. În ciuda numelui, lista nu deține un **DefaultListModel** decât dacă acest lucru este setat explicit ​din program.
  
 +<note warning>
 +Dacă **DefaultListModel** nu este potrivit nevoilor programatorului,​ se poate scrie un model customizat dar care trebuie să adere la interfața **ListModel**.
 +</​note>​
  
-=== Crearea butoanelor ===+Altă metodă de adăugare, cu specificare exactă a poziției de inserare, este cea care uzitează metoda //​insertElementAt//​. Ștergerea este, de asemenea, foarte simplă, deoarece există metoda //remove//.
  
-Un buton poate fi creat folosind clasa **//​JButton//​**De obiceibutonul este contruit +<code java> 
-folosind unul dintre constructorii:​+listModel.insertElementAt(employeeName.getText()index); 
 +listModel.remove(index);​ 
 +</​code>​
  
-    * **//public JButton(); // un buton fara text//** +== 1.6 Formatarea celulelor ==
-    * **//public JButton(String text) // un buton cu text dat ca parametru//​** +
-    * **//public JButton(String text, Icon ico) // buton cu text si imagine//**+
  
 +O listă folosește un obiect numit **Cell Renderer** pentru a-și afișa intrările. Cel implicit știe să afișeze șiruri de caractere și imagini și afișează tipul **Object** invocând metoda //​toString()//​.
  
 +Dacă se dorește schimbarea modului în care se face afișarea sau dacă se dorește un comportament diferit față de cel oferit de //​toString()//,​ se poate implementa un **Cell Renderer** customizat.
  
-Textul ​de pe buton poate fi modificat folosind ​metoda **//setText(String ​text)//​** ​sau poate fi preluat folosind metoda ​**//getText()//​**. ​Metodele ​**//setLabel()//​** ​si **//getLabel()//​** ​sunt considerate obsolete si nu se mai folosesc in prezent.+Pașii ce trebuie urmați sunt: 
 + 
 +  * scrierea unei clase care implementează interfața **ListCellRenderer**;​ 
 +  * crearea unei instanțe ​de clasă și apelarea metodei //​setCellRenderer()//​ pentru listă, folosind instanța ca argument. 
 + 
 +=== 2. Tabele === 
 + 
 +== 2.1 Introducere == 
 + 
 +Clasa **JTable** este folosită pentru a afișa și edita tabele de celule în două dimensiuni. 
 + 
 +**JTable** deține numeroase facilități care permit customizarea după preferințe dar în același timp oferă și opțiuni standard pentru aceste facilități astfel încât tabele simple pot fi create foarte rapid și ușor. 
 + 
 +De exemplu, un tabel cu 10 linii și 10 coloane se poate obține astfel: 
 + 
 +<code java> 
 +TableModel dataModel = new AbstractTableModel() { 
 +    public int getColumnCount() { return 10; } 
 +    public int getRowCount() { return 10; } 
 +    public Object getValueAt(int row, int col) { 
 +        return new Integer(row * col); 
 +    } 
 +}; 
 +JTable table = new JTable(dataModel);​ 
 +JScrollPane scrollpane = new JScrollPane(table);​ 
 +</​code>​ 
 + 
 +<note important>​ 
 +Când se dorește scrierea de aplicații care folosesc **JTable**, este necesar să se acorde puțină atenție structurilor de date care vor reprezenta datele din table. 
 + 
 +**DefaultTableModel** este o implementare de model care folosește un vector de vectori de obiecte (de tipul **Object**) pentru a stoca valorile din celule. 
 +</​note>​ 
 + 
 +La fel cum se pot copia datele dintr-o aplicație în instanța **DefaultTableMode**,​ este, de asemenea, posibil să se ascundă datele în metodele interfeței **TableModel** astfel încât acestea să poată ​fi transmise direct către **JTable**, la fel ca în exemplul de mai sus. 
 + 
 +Această abordare duce deseori la aplicații mai eficiente, deoarece modelul este liber să aleagă reprezentarea internă care se potrivește cel mai bine datelor manipulate. 
 + 
 +<note tip> 
 +Se recomandă folosirea **AbstractTableModel** ca și clasă de bază pentru crearea de subclase, respectiv **DefaultTableModel** atunci când subclasa nu este necesară. 
 +</​note>​ 
 + 
 +== 2.2 Folosirea variabilelor întregi == 
 + 
 +**JTable** folosește exclusiv variabile întregi pentru a referi liniile și coloanele modelului pe care îl afișează. Este folosită ​metoda ​//​getValueAt(int,​ int)// pentru a întoarce valorile din model pe parcursul desenării. 
 + 
 +Coloanele pot fi rearanjate în tabel astfel încât acestea să apară într-o ordine diferită față de cea din model. Acest fapt nu afectează deloc implementarea:​ atunci când coloanele sunt rearanjate, obiectul de tip **JTable** menține intern noua ordine și convertește indicii coloanelor înainte de orice interogare a modelului. 
 + 
 +<note important>​ 
 +Așadar, la programarea unui **TableModel**,​ nu este necesară ascultarea după evenimente de reordonare de coloane, întrucât modelul va fi interogat în sistemul propriu de coordonate indiferent de ce se întâmplă la vizualizare. 
 +</note> 
 + 
 +== 2.3 Metode de printare == 
 + 
 +În versiunea curentă de Java sunt adăugate metode la clasa **JTable** care permit acces convenabil către nevoi obișnuite de afișare. Noile metode ​//print()// adaugă cu ușurință suport de printare aplicației ce se dorește a fi dezvoltată. 
 + 
 +În plus, noua metodă //​getPrintable(javax.swing.JTable.PrintMode,​ java.text.MessageFormat,​ java.text.MessageFormat)// este disponibilă pentru necesități avansate. 
 + 
 +La fel ca pentru toate clasele ​**JComponent**,​ se pot folosi **InputMap** și **ActionMap** pentru a asocia o acțiune cu tasta și a executa acțiunea în condiții specificate. 
 + 
 +=== 3. Arbori === 
 + 
 +== 3.1 Introducere == 
 + 
 +Clasa **JTree** permite afișarea datelor ierarhice (sub forma unei schițe). 
 + 
 +Un nod specific ​poate fi identificat fie printr-un ​**TreePath** (un obiect care încapsulează nodul și toți strămoșii acestuia), fie prin linia de afișare, unde fiecare linie din zona de afișare conține un singur nod. 
 + 
 +== 3.2 Tipuri de noduri == 
 + 
 +  * **Nod expandat** - este un nod care nu este frunză (metoda ​//TreeModel.isLeaf(node)// întoarce //false//) și care își va afișa copiii când toți strămoșii săi sunt expandați;​ 
 +  ​* **Nod colapsat** - este un nod care își ascunde copiii; 
 +  * **Nod ascuns** - este un nod care este situat sub un strămoș colapsat; 
 +  * **Nod afișat** - toți părinții unui nod care poate fi vizualizat sunt expandați, dar aceștia pot sau nu fi afișațiUn nod afișat se regăsește în zona de afișare și poate fi vizualizat. 
 + 
 +<note warning>​ 
 +Următoarele metode din clasa **JTree** folosesc cuvântul "​visible"​ pentru a se referi la "​afișat":​ 
 + 
 +  ​* //isRootVisible()//
 +  ​//​setRootVisible()//;​ 
 +  ​//​scrollPathToVisible()//;​ 
 +  ​//​scrollRowToVisible()//;​ 
 +  ​* //getVisibleRowCount()//
 +  ​//​setVisibleRowCount()//​. 
 + 
 +Următorul grup de metode folosesc cuvântul "​visible"​ pentru a se referi la "poate fi vizualizat"​ (sub un părinte expandat):​ 
 + 
 +  ​//​isVisible()//;​ 
 +  * //​makeVisible()//​. 
 +</​note>​ 
 + 
 +== 3.3 Detectarea schimbării selecției == 
 + 
 +Pentru a detecta schimbarea selecției, ​se va implementa interfața **TreeSelectionListener** și se va adăuga o instanță folosind //​addTreeSelectionListener()//​. Metoda //​valueChanged()//​ va fi invocată atunci când utilizatorul selectează alt nod, și doar o dată, chiar dacă se efectuează un click de două ori pe același nod. 
 + 
 +Cu toate acestea, pentru a face separarea cazurilor de dublu click, indiferent de selecția anterioară,​ este recomandată abordarea prezentată în codul prezentat ​mai jos. 
 + 
 +<code java> 
 +// final JTree tree = ...; 
 +MouseListener ml = new MouseAdapter() { 
 +    public void mousePressed(MouseEvent e) { 
 +        int selRow; 
 +        selRow = tree.getRowForLocation(e.getX(),​ e.getY());​ 
 +        TreePath selPath; 
 +        selPath = tree.getPathForLocation(e.getX(),​ e.getY());​ 
 +        if (selRow != -1) { 
 +            if (e.getClickCount() == 1) { 
 +                mySingleClick(selRow,​ selPath); 
 +            } 
 +            else if (e.getClickCount() == 2) { 
 +                myDoubleClick(selRow,​ selPath); 
 +            } 
 +        } 
 +    } 
 +}; 
 +tree.addMouseListener(ml);​ 
 +</​code>​ 
 + 
 +== 3.4 Afișarea și editarea nodurilor == 
 + 
 +Pentru afișarea nodurilor complexe (de exemplu, noduri conținând atât text, cât și o icoană) se va implementa interfața **TreeCellRenderer** și se va folosi metoda //​setCellRenderer(javax.swing.tree.TreeCellRenderer)//​. 
 + 
 +Pentru a edita astfel de noduri, se va implementa interfața **TreeCellEditor** și se va folosi metoda //​setCellEditor(TreeCellEditor)//​. 
 + 
 +<note tip> 
 +Precizările legate de **InputMap** și **ActionMap** sunt aceleași ca pentru **JTable** (din secțiunea anterioară). 
 +</​note>​
  
poo/breviare/breviar-10.1543326778.txt.gz · Last modified: 2018/11/27 15:52 by matei.teodorescu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0