A. Veneziani - Elementi di programmazione con interfacce grafiche
←
→
Trascrizione del contenuto della pagina
Se il tuo browser non visualizza correttamente la pagina, ti preghiamo di leggere il contenuto della pagina quaggiù
A. Veneziani – Elementi di programmazione con interfacce grafiche IDE di sviluppo grafiche Quasi tutte gli ambienti di sviluppo grafico per programmazione di applicazioni desktop tradizionali sono ormai basati su una comune impostazione che negli anni si è rivelata pratica e capace effettivamente di aumentare la capacità di programmazione del programmatore. Un elemento fondamentale per migliorare lo sviluppo è stato quello di integrare le varie fasi dello stesso in un unico tool che le rendesse sincroniche e facili da richiamare, così come possibile passare velocamente dall’una all’altra. In questo senso si cominiciò tanti anni fà a parlare di IDE di sviluppo, piuttosto che di semplici compilatori e tool di sviluppo. Una IDE era qualcosa che integrava in modo armonico i vari tool permettendone un uso più veloce ed ottimizzato, e di richiamare ed utilizzare le varie fasi tipiche dello sviluppo in modo assai più veloce. Questo passaggio si ebbe, almeno a livello di software commerciale, con l’apparizione di prodotti tipo il Turbo Pascal della Borland, quindi già nei primi anni ’80. Un altro passo importante fù quello di dotare tali ambienti integrati di ulteriori funzionalità che fossero di ausilio alla programmazione. La principale di queste, che ancor oggi è assai importante, è la presenza di funzionalità di debugging sempre più avanzate. Nei vecchi tool di sviluppo, esistevano già dei debugger, ma essi erano di uso poco intuitivo ed erano staccati dal resto dei tool di programmazione. Successivamente i debugger vennero profondamente integrati nelle IDE e ne divennero una parte fondamentale e sempre più evoluta, permettendo una individuazione degli errori sempre più comoda e veloce, oltre e rendere spesso possibile un apprendimento del linguaggio e del suo comportamento più veloce e chiaro nel settore educational. Infine all’inizio degli anni ’90 si ebbe un ulteriore step evolutivo. Sul computer più diffuso del momento, il PC, appare il primo sistema operativo con interfaccia grafica a larga diffusione: Windows 3.0. Pur con tutta una serie di limiti dovuti alla relativa parentela con DOS e limitazioni dovute alla sua architettura, questo sistema operativo impone di introdurre massicciamente la programmazione “a finestre” o con interfaccia grafica anche sul PC, la macchina più diffusa del mondo. In un primo momento tale programmazione è complessa e solo per “addetti ai lavori”, ma successivamente appaiono via via tools che permettono con facilità sempre crescente di creare applicazioni desktop grafiche. Il principe fra questi tool è senz’altro Visual Basic della stessa Microsoft, che già agli inizi degli anni ’90 propone un procedimento di programmazione dell’ interfaccia grafica molto intuitivo e veloce, dove altrimenti il programmatore avrebbe dovuto scrivere numerose linee di codice, da modificare e ritoccare magari spesso. Si parla comunemente da quel momento di programmazione “visuale”, per indicare un tipo di procedimento che si avvale di tool appositi, di solito interni alla IDE di sviluppo, per disegnare (nel vero senso del termine) una interfaccia grafica che poi sarebbe stata collegata al codice sottostante di programma. Questo paradigma di sviluppo poi accettato universalmente da tutte le IDE (da Netbeans a Visual Studio a molte altre), ha potenziato e velocizzato molto la parte di disegno grafico dei programmi. Altri ausilii, ormai irrinunciabili, sono le funzionalità di autocompletamento del codice, spesso utilissime come promemoria del programmatore. Il sistema di sviluppo suggerisce quali scelte possa fare il programmatore mentre stà scrivendo codice. Numerose altre sono le funzionalità di una IDE moderna, ma sostanzialmente essa deve essere vista come un raggruppamento di strumenti, ormai estremamente evoluto. Pagina 1
Le famiglie di componenti Un sistema operativo, come forse avrete già sperimentato, ha molteplici modi di essere programmato. Come prima differenza esistono vari linguaggi che permettono la programmazione del sistema operativo stesso. Molti tra l’altro permettono di programmare in modo e con sintassi simili, sistemi operativi differenti, ottenendo gli stessi risultati. Un altra fonte di differenze è che le interfacce grafiche vengono di solito programmate con serie di componenti che vanno a formarle e dare loro le funzionalità necessarie o previste. In realtà questo strato software a componenti (basato totalmente sulla programmazione ad oggetti), non è univoco, vale a dire non esiste una serie di componenti per Windows, ma bensì più serie e lo stesso vale anche per Linux e gli altri sistemi operativi. Esistono quindi varie serie di componenti “grafici”, tra loro usualmente non compatibili. Si potrebbe parlare più giustamente di famiglie di componenti grafici. Di solito in ongnuna di tali famiglie esiste una serie di componenti di base considerata per uso “standard” e poi un’altra serie più o meno numerosa di componenti aggiuntivi che permettono speciali funzionalità. Questi componenti aggiuntivi in alcune famiglie di componenti sono numerossissimi e spesso programmati da società terze che si occupano solo di questo compito. Così ogni “piattaforma” o linguaggio di sviluppo ha serie di componenti diversi e propri. Ad esempio Java ha dei componenti detti Swing (multipiattaforma come il linguaggio Java), .NET ed i linguaggi che dipendono da esso ha le Windows Forms e alcune altre tecnologie sempre a componenti differenti, Delphi e C++ Builder due linguaggi di notevole successo soprattutto in anni passati si basano ed utilizzano la libreria di componenti detta VCL, in precedenza a .NET lo standard Microsoft per i componenti era quello denominato ActiveX / COM, mentre nel mondo open, molte altre librerie di componenti sono disponibili a seconda del linguaggio e tool di sviluppo utilizzato (ad esempio wxWidget e Qt o Lazarus (Object Pascal) con i componenti LCL). Queste famiglie di componenti differiscono tra loro per la metodica e alcuni standard propri della famiglia stessa di componenti ed eventualmente dal linguaggio nel quale sono programamati. Questo fà si che quasi sempre varie famiglie di componenti non siano utilizzabili per realizzare la stessa applicazione. Tipicamente i componenti più comuni che si trovano in tutti i set di componenti grafici sono quelli base che troviamo di continuo in una interfaccia grafica di un qualsiasi sistema operativo, quali pulsanti (button), etichette (label), caselle di testo (textbox), liste a discesa (combobox), liste (listbox), caselle di spunta (checkbox), pulsanti radio (radiobutton) ecc. Il componente fondamentale però è sempre quello che permette di tenere assieme gli altri componenti e raggruppare l’interfaccia, ossia la finestra (o form). I vari componenti vengono quindi disposti su di essa. Componenti e programmazione ad oggetti Inizia in questo periodo, ossia all’inizio degli anni ’90 la diffusione massiccia della programmazione ad oggetti, dovuta al fatto che tutti gli elementi base di una interfaccia grafica sono degli oggetti, con loro prorietà e metodi. E proprio per questo che l’ inizio dell’era della programmazione desktop con interfacce grafiche, coindice con lo sviluppo e l’uso impetuoso di molteplici linguaggi basati sulla OOP (Object Oriented Programming). Anche linguaggi tradizionali attorno circa a questo periodo iniziano a trasformarsi ed integrare sempre maggiori funzionalità ad oggetti, quali C (evolutosi in C++) e Pascal (evolutosi in diversi dialetti di Object Pascal). I programmi via via divengono più complessi e massicci e sempre più prende piede anche una programmazione che si appoggia a librerie, perciò in questi sistemi operativi appare comune l’uso e Pagina 2
l’interazione con .DLL. Come noto, dopo qualche tempo, nascono nuovi linguaggi non direttamente derivati da precedenti, e fortemente basati sulla OOP quali Java (1995) e successivamente C# (2000). Un componente grafico quindi ha una sua apparenza grafica e nel contempo essendo un oggetto ha proprietà, spesso legate al suo aspetto, e metodi per indurre modifiche e comportamenti dell’oggetto stesso. Un esempio di semplice progetto (C#) Realizziamo ora un semplice esempio di programma con interfaccia grafica in C# e Visual Studio. Il programma dovrà solo effettuare una somma tra interi e quindi sarà realizzato tramite tre label, tre box di testo, e un pulsante, oltre che ad una form che contenga il tutto. Le tre label (componente Label di Windows Forms), saranno opportunamente posizionate (magari sopra le box di testo o al loro fianco a sinistra), e l’unica proprietà che verrà cambiata sarà la Text, tramite cui cambierà la scritta all’ interno della label stessa. Per ottenenre le label selezioneremo il componente Label nella Barra degli Strumenti e poi faremo click sulla form dove vorremo che il componente appaia. A questi componenti dato che essi non verranno modificati (in quanto queste scritte sono fisse) e non interagiranno con il programma potremo evitare di dare loro un nome specifico, quindi rimarrà quello di default dato da Visual Studio. Successivamente inseriremo sulla form tre box di testo (o caselle di testo) capaci di recepire input e di svolgere anche funzioni di output. Nel caso del primo e secondo numero (i due addendi) ci servono per recepire dati, mentre nel terzo caso, per il terzo elemento usato in output è possibile usare una box di testo o una label indiferentemente. Di queste modifichiamo la prorietà Name, dando un nome a dognuno di questi componenti, quali, txtAdd1, txtAdd2, txtRisultato, di modo da poter individuare univocamente ogni componente. Poi modifichiamo la proprietà Text di modo che la casella di testo all’inizio risulti vuota. Di queste box potremo cambiare anche l’allineamento del testo per renderlo coerente con il trattamento di dati numerici, quindi opereremo sulla proprietà TextAlign, selezionando il valore Right. Inoltre per la Pagina 3
txtRisultato potrà essere impostata la proprietà Readonly a True, dato che essa non deve servire da input di dati, ma solo come visualizzazione di un risultato. Successivamente si dispongono le textbox opportunamente sulla form. Gli allineamenti tra i componenti saranno segnalati da apposite linee blu, del sistema di disegno dell’interfaccia. Infine inseriremo sempre con la solita procedura un pulsante (Button), dando ad esso un testo (proprietà Text), ad esempio “Somma”, modificando opportunamente posizione e dimensioni e associandogli un nome diciamo btnSomma. A questo punto non resta che operare qualche regolazione sulla form di base sulla quale i vari componenti sono stati aggiunti. Di norma non è necessario variare il suo nome, ma semmai altri parametri tra cui: Text – per inserire un nuovo titolo della form Icon – per assegnare una nuova icona alla form (icona non presente se bordo fisso) FormBorderStyle – per definire le proprietà del bordo della form. Varieremo questa proprietà a FixedDialog, per far si’ che la form non abbia un bordo ridimensionabile. MaximizeBox – a false per interdire la possibilità della form di essere massimizzata. Dopo queste modifiche relativamente semplici, ed aver dimensionato opportunamente la nostra form, la realizzazione della nostra interfaccia è terminata e quindi apprestiamoci a scrivere del codice C#. Per far ciò selezioneremo la sezione Events (Eventi) della finestra Properties (Proprietà). Selezioneremo quindi il componente pulsante e cercheremo l’evento Click che è quello che vogliamo associare al pulsante stesso. Per confermare l’associazione basterà fare doppio click nella casella corrispondente dell’evento. In essa apparirà una scritta corrispondente al nome della routine –evento (metodo), relativo all’evento. Tale metodo verrà richiamato solo quando un evento di quel tipo accadrà su quell’elemento, nel nostro progetto il pulsante Somma. A questo punto sarà apparso automaticamente del nuovo codice nel listato del progetto (modulo di codice della form, denominato di default Form1.cs), ossia il metodo legato all’evento Click. In tale metodo andrà inserito il codice che deve essere eseguito alla pressione del pulsante, ossia quello che effettua l’operazione di somma. Il metodo verrà richiamato quando l’evento click sarà effettuato sul pulsante Somma. Il codice che và inserito nel metodo è: private void btnSomma_Click(object sender, EventArgs e) { int n1, n2, ris; n1 = Convert.ToInt32(txtAdd1.Text); n2 = Convert.ToInt32(txtAdd2.Text); ris = n1 + n2; txtRisultato.Text = Convert.ToString(ris); } La comprensione del codice è piuttosto semplice. a) Si dichiarano tre variabili intere utili al calcolo b) Si legge il contenuto delle box di testo txtAdd1 e txtAdd2, assegnandolo alle var. n1 e n2 c) L’assegnazione, dato che le box txtAdd1 e txtAdd2 contengono stringhe deve essere preceduta da una conversione. d) La conversione di cui sopra in .NET avviene tramite una apposita classe detta Convert. Il metodo ToInt32 passa ad un intero a 32 bit. e) I valori scritti in txtAdd1 e txtAdd2 possono essere acquisiti e passano in n1 ed n2. f) Viene effettuata la somma ed il risultato messo nella var. intera ris. Pagina 4
g) In questo caso il problema è inverso. Si ha un valore intero e si vuole renderlo visibile in txtRisultato. txtRisultato può contenere solo testo (stringa). h) Si utilizza ancora la Convert in questo caso con il metodo ToString che converte a stringa da intero. In questo modo si ottiene nella box di testo txtRisultato il risultato voluto. Lo stesso esempio in C++ Builder C++ Builder è un potente ambiente RAD (Rapid Application Development) che permette velocemente e con una certa semplicità di sviluppare applicazioni con interfaccia grafica, esso utilizza una versione relativamente standard del linguaggio C++, con alcune estensioni proprietarie, dovute soprattutto alla libreria VCL fulcro del sistema di programmazione di interfacce grafiche. Come tutti i RAD ed analogamente a Visual Studio, C++ Builder utilizza la programmazione “visuale” dell’interfaccia, ossia dei tools a due vie dove le modifiche alle proprietà hanno effetto (eventualmente) sul disegno dell’interfaccia e modifiche al disegno vengono automaticamente recepite e registrate nelle relative ed opportune proprietà degli oggetti che la costituiscono. Come si vede anche in C++ Buider esiste la sezione per comporre e disegnare l’interfaccia grafica, quella per regolare le proprietà, e la barra dei vari componenti (in questo caso della lbreria VCL). Pagina 5
Il procedimento è del tutto simile a quello indicato per il programma in C# con Visual Studio, ma cambia il nome dei componenti e di alcune proprietà. In questo caso la label, sarà indicata con Tlabel, che è poi la classe che definisce una label generica VCL. La proprietà da regolare per cambiare il testo interno delle label in questo caso sarà denominata Caption. Le text box in questo ambiente hanno nome TEdit. In questo progettino le sono state assegnate i valori edtAdd1, edtAdd2, ed edtRis. Le proprietà da modificare per il nome saranno la Name e per regolare il contenuto si agirà sulla proprietà Text. Infine per rendere di sola lettura la edtRis, si opererà sulla proprietà Readonly (nome analogo a quello che troviamo in .NET !) del componente edtRis. Anche qui potremo regolare l’allineamento del testo nelle editbox (box di testo), cone la proporietà Alignment, che dovrà essere regolata a taRightJustify. Infine la form di base potrà essere regolata come in Visual Studio con le proprietà: Caption – regola il titolo della form Icon – regola l’icona della form BorderStyle – serve per imporre alla form un bordo fisso. Regolato a bsSingle BorderIcons -> biMaximize a False, per disattivare il tasto per massimizzare la form. Successivamente si accede alla tab Events dell’Object Inspector e si associa un evento Click al pulsante Somma, in modo del tutto simile a quello effettuato su Visual Studio. Appare anche qui in modo automatico del codice C++ (anche qui sotto forma di metodo) dove inserire del codice di programma. void __fastcall TForm1::btnSommaClick(TObject *Sender) { int n1, n2, ris; n1 = StrToInt(edtAdd1->Text); n2 = StrToInt(edtAdd2->Text); ris = n1 + n2; edtRisultato->Text = IntToStr(ris); } Il significato della sintassi del metodo è che esso non rende valori (void), utilizza eventualmente e preferenzialemente dei registri per il passaggio di valori dei parametri (__fastcall), e che la classe Tform1, ha un metodo (definito al di fuori della classe stessa) di nome btnSommaClick. Il parametro Sender indica chi è il componente (genericamente l’oggetto, quindi TObject) che ha chiamato la routine-evento. In questo caso vediamo che C++ Builder mette a nostra disposizione funzioni di conversione diverse da .NET. Esse fanno parte della libreria VCL, e trasformano AnsiString (una particolare forma di string propria di VCL in intero) in intero StrToInt(...) e viceversa IntToStr(...). La proprietà Text permette come già detto di accedere al testo delle caselle di testo (box di testo). I principali componenti e le loro proprietà Nei nostri programmi didattici useremo quasi sempre componenti “standard”, vale a dire quelli che in C++ Builder sono indicati nella tab “Standard” e in Visual C# nel gruppo di componenti “Common controls” o componenti comuni, vale a dire pulsanti (button), caselle di testo (textbox), etichette (label), listbox, Pagina 6
combobox, pulsanti radio (radiobutton), caselle di spunta (checkbox), ed altri di uso comune su tutti sistemi operativi con interfaccia grafica, specificamente Windows, Linux e Mac OS. Esiste poi in tutti i linguaggi “visuali”, un altro componente che agisce come substrato (o contenitore) per gli altri, vale a dire il form (o finestra). Un programma grafico, come ben noto può essere costituito da più form, i quali possono entrare in azione in momenti diversi dell’esecuzione del programma stesso. Per inserire uno di questi componenti sulla form, si seleziona lo stesso dalla barra degli strumenti (toolbox) e si riporta sulla form, dove è possibile ridimensionarlo e riposizionarlo a piacere. Queste operazioni regolano automaticamente due importanti proprietà del componente stesso, vale a dire Top (distanza dall’alto della form, senza contare la barra del titolo) e Left (distanza dal bordo sinistro della form) per il riposizionamento, e Width (larghezza del componente) ed Height (altezza del componente) per il ridimensionamento1. Tutti i componenti inseriti, soprattutto quelli che abbiano interazioni con il codice di programma, è opportuno che abbiano un nome ben preciso e riassegnato dal programmatore. Il nome di un componente, già presente con un valore di default, può essere riassegnato dal programmatore con la proprietà Name (che ha lo stesso nome e scopo sia in Windows Form che nelle VCL). Essa permette di ridenominare opportunamente ed in maniera più propria, rispetto agli scopi nel progetto, ogni componente presente. Usualmente è buona norma indicare con una sigla (di solito di tre le lettere) la tipologia del componente e poi affiancarne il nome vero e proprio. Ad esempio: lblValore, btnOk, txtContatore, ecc. Questa regolazione manuale delle proprietà, come quelle di tutte le altre proprietà può essere fatta inserendo valori nella apposita griglia delle proprietà, denominata in Visual C# (Proprietà o Properties) ed in C++ Builder2 nella tab Properties della finestra Object Inspector. Le proprietà indicate sopra hanno gli stessi nomi anche in C++ Builder e nella serie di componenti VCL. Le proprietà possono venir modificate a design-time, ma ovviamente non durante l’esecuzione del programma, dove solo il codice ha la capacità di influenzare il layout stesso. A questo proposito bisogna tener presente che esistono tre stati possibili della IDE (sia in Visual Studio che C++ Builder): Design time - il programma è fermo ed è possibile disegnare l’interfaccia e regolare le proprietà dei componenti Run-time – Il programma è in esecuzione e NON è possibile disegnare o modificare l’interfaccia o regolare le sue proprietà (ed in Visual C#, neppure modificare il codice) Debug-time – Si tratta di uno stato particolare nel quale si effettua il debug del programma, ossia la sua esecuzione controllata. In tale stato è possibile visionare il contenuto delle variabili, alterarne il valore, visionare l’esecuzione in modalità passo-passo, osservando quali istruzioni vengano eseguite. Analizziamo in dettaglio quindi alcuni di questi componenti: Altre proprietà comuni a vari controlli Esistono altre proprietà che sono comuni a diversi controlli che si possono incontrare sulle interfacce. Tra queste abbiamo analizzato: Visible – permette la visibilità o meno di un componente (se è un componente visualizzabile sull’interfaccia grafica). E’ booleana. E’ analoga e ha lo stesso effetto sia in Windows Form che VCL. 1 In Visual C# Top e Left sono utilizzabili nel codice di programma, al momento della regolazione manuale della posizione si deve utilizzare le componenti X e Y della proprietà Location. 2 Attualmente non esiste una versione italiana di C++ Builder, che è disponibile in Inglese e poche altre lingue. Pagina 7
Se il componente ha tale proprietà a false non è visibile a run-time (esecuzione) , mentre come logico lo è a design time, ossia mentre si disegna / modifica l’interfaccia. Enable – Indica che il componente è abilitato o meno. Un componente disabilitato è visibile, ma non svolge le sue funzioni e non attiva gli eventuali eventi ad esso associati. Il controllo apparirà graficamente con colori più sfumati in certi dettagli, quali scritte da colore nero a colore grigio ed effetti similari. Form E’ il componente fondamentale per la realizzazione di programmi con interfacce grafiche. Realizza le famose “finestre”, sulle quali, grazie ad altri componenti, sono implementate le funzionalità volute. Funge quindi da base per tutti gli altri componenti. Anch’essa possiede le proprietà “universali”, Top, Left, Width ed Height, oltre che Name. In particolare il valore di Top e Left si riferiscono però in questo caso al sistema di coordinate dello schermo, quindi sono calcolate rispetto all’angolo in alto a sinistra dello schermo. Di una form usualmente si desidera anche cambiare il titolo, e ciò può essere fatto tramite la proprietà: Text (Visual C#) Caption (C++ Builder) Talora si vuole rendere la form con il bordo fisso (frequentemente in progettini semplici come i nostri). Per far questo si dovrà alterare le proprietà: FormBorderStyle cambiandola da Sizable a FixedSingle (in Visual C#) BorderStyle cambiandola da bsSizable a bsSingle (C++ Builder) Inoltre abbiamo visto che può essere utile eliminare la possibilità di massimizzare la finestra (form), interdicendo il pulsante di massimizzazione della stessa, ossia regolando la proprietà: MaximizeBox a false (Visual C#) BorderIcons sottosezione biMaximize a false (C++ Builder)3 Inoltre in entrambi i sistemi di sviluppo (Visual C# e C++ Builder) è possibile modificare l’icona sulla form tramite la modifica della proprietà Icon. Label (Windows Form) / TLabel (VCL) E’ un componente atto a visualizzare una scritta. Non permette la scrittura diretta da parte dell’utente, ma solo, eventualmente, quella da parte del programma (quindi è un componente che può eventualmente, essere usato per il solo output di dati. Le principali proprietà del componente sono: Text (Visual C#) Caption (C++ Builder) Per modificare la scritta stessa. Inoltre sia nelle VCL che in Windows Form, è abilitata di default la proprietà Autosize, che ridimensiona automaticamente la label a seconda della scritta in essa presente. Tale proprietà per vari motivi (ad esempio una label che inizialmente non contiene testo tende a divenire poco visibile nel progetto grafico) può essere disabilitata (false). Nel caso Autosize sia quindi a false la label può essere liberamente ridimensionata. Inoltre abbiamo visto nel progetto dell’orologio che è possibile (come del resto in altri controlli) modificare la dimensione e il font del testo della label, regolando: Font sottosezione Name Font sottosezione Size (in Visual C#) Pagina 8
E Font sottosezione Name Font sottosezione Size (in C++ Builder) Specifico che la regolazione di tali proprietà è meccanica ed intuitiva tramite l’’interfaccia grafica a design time, ma un po’ più complessa e meno ovvia se si dovesse effettuare via codice. Ecco due spezzoni di programma che regolano gli stessi aspetti in C# e C++ Builder: label1.Font = new Font("Consolas", 20); // Visual C# e this->Label1->Font->Name = "Consolas"; this->Label1->Font->Size = 20; // C++ Builder dove this è la form che ospita il componente (tlabel1 nel nostro caso). E’ eventualmente possibile cambiare il colore di background di una label (cosa che potrebbe essere utile per vari motivi), con le proprietà: Per C++ Builder bisognerà regolare 2 proprietà: 1. Trasparent a false (regola la trasparenza del componente - fondo opaco o trasparente ) 2. Color al valore del colore voluto Usualmente i colori stadard in C++ Builder sono costanti predefinite il cui nome inizia con cl…., ad esempio clRed, cl Yellow, ecc.. Per Visual C#: Regolare la proprietà BackColor ad un colore voluto Come si nota dopo la regolazione, la proprietà è definita da una terna di valori tra 0 e 255, ognuno dei quali regola uno dei colori fondamentali R (rosso), G (verde), B (blu). TextBox (Windows Form) / TEdit (VCL) E’ un componente che permette all’utente di inserire dei dati (di default su una sola riga). Il suo contenuto può anche essere scritto dal programma, e quindi si comporta come una zona dell’ interfaccia per l’input-output di dati. Se il desiderio del programmatore è che solo il programma possa scrivere nella casella di testo, si dovrà regolare la proprietà Readonly a true (di default è a false). In questo caso non è più possibile scrivere dati nel componente ed esso diviene di solo output (in modo simile alla Label). La proprietà Readonly (booleana) è presente con lo stesso nome e significato sia in Windows Form che il VCL. Per alterare o leggere il testo del componente casella di testo (TextBox in Windows Form, TEdit in VCL), si utilizza la proprietà Text (con lo stesso nome e significato sia in Windows Form che in VCL). In alcuni progettini abbiamo modificato l’allineamento delle textbox dato che esse erano destinate a contenere valori numerici (di solito allineati a destra), mentre l’allineamento di default delle textbox / tedit è a sinistra (previsto per dati alfanumerici di tipo generico). Per modificare tale aspetto esiste una apposita prorietà: TextAlign (di default a left) da portare a right (Visual C#) Alignment (di default a taLeftJustify) che và portata a taRightJustify (C++ Builder) E’ possibile variare il colore della textbox / tedit con: Proprietà Color (in C++ Builder) Proprietà BackColor (Visual C#) Pagina 9
Button (Windows Form) / TButton (VCL) Si tratta del comune pulsante o bottone, di cui sono piene le finestre di Windows e altri sistemi operativi. Le dimensioni e posizione sono regolabili con le proprietà generali di cui si è parlato in precedenza. La scritta sul pulsante che descrive le sue funzionalità viene modificata tramite la proprietà: Text (in Visual C#) Caption (in C++ Builder) Ovviamente anche nei pulsanti possono essere variate le proprietà Enabled e Visible, con gli effetti detti in precedenza. Ai pulsanti è spesso frequente associare l’evento click, il più usato per questo tipo di componenti. La metodica è simile sia per C++ Builder che per Visual C#: 1) Si seleziona il componente sulla form 2) Si assegna ad esso il nome desiderato con la proprietà Name 3) Ci si sposta su Object Inspector (C++ Builder) o sulla finestra Prorietà (Visual C#) 4) Si seleziona la tab Events dell’ Object Inspector (C++ Builder) o il pulsante apposito in Prorietà (Visual C#) 5) Nella lista dei tipi di evento associabili al componente si cerca l’evento di tipo Click (OnClick per C++ Builder) (Click per Visual C#) 6) Si effettua doppio click nella casella bianca di lato 7) Automaticamente il tipo di evento viene associato al componente e la relativa routine (metodo) evento appare nel codice scritta in modo automatico 8) Aggiungere adesso il codice desiderato all’interno della routine evento, che dovrà essere eseguito quando l’evento viene richiamato. Radiobutton (Windows Form) / TRadioButton (VCL) In un progetto proposto e realizzato come esercitazione di laboratorio è stata utilizzata una serie di pulsanti radio, altrimenti detti in inglese radiobutton. Questi controlli operano in gruppo e la selezione di ognuno di essi è alternativa alle altre dello stesso gruppo, vale a dire solo un radio di un certo gruppo può essere in uno stato di selezione. I controlli radio sia in Windows Form che in VCL hanno anche annessa una scritta abbinata al radio stesso, esplicativa della voce selezionata. Un solo gruppo di radio può essere utilizzato in modo piuttosto semplice. Basta posizionare i radiobutton sulla form, dare loro dei nomi (diversi) e controllare il loro stato di selezione, tramite la proprietà Checked. Tale proprietà è presente con lo stesso nome e significato sia In Windows Form che nelle VCL, ossia permette di controllare se un certo radio sia o no selezionato. Nel caso sulla form fosse necessario avere più gruppi indipendenti di radio, allora: In Windows Form incolla prima uno speciale componente di raggruppamento detto GroupBox. Su di esso si “incolla” il primo gruppo di radio. Si ripete l’operazione con altri eventuali gruppi. In tale modo i vari gruppi agiscono in modo indipendente. La proprietà Text del componente permette di regolare la scritta esplicativa del gruppo stesso di componenti. Una metodica del tutto simile si utilizza con la libreria di componenti VCL. Anche qui esiste uno specifico componente capace di creare gruppi di radio e farli funzionare in modo indipendente, esso è detto TGroupBox e fa parte della palette dei componenti Standard. Per aggiungere i componenti radio al groupbox si selezionano i radio e si rilasciano sul groupbox. I componenti radio all’ interno di ogni groupbox lavorano in modo indipendente. Pagina 10
La proprietà Caption del componente permette di regolare la scritta esplicativa del gruppo stesso di componenti. Timer (Windows Form) / TTimer (VCL) E’ un componente che è stato utilizzato ad esempio nel progettino dell’orologio digitale. Si tratta di un componente capace di produrre ciclicamente eventi ad intervalli di tempo predeterminati dal programmatore. L’evento che può essere associato al Timer è uno solo ed è OnTimer nelle VCL e Tick in Windows Form. Il componente TTimer si trova nel gruppo di componenti System in C++ Builder e Timer nel gruppo Components in Visual C#. Il componente Timer / TTimer non è mai visibile, quindi non è un componente grafico. Nonostante ciò, per aggiungere lo stesso al progetto si opera come se esso fosse un componente come gli altri ossia visibile. L’icona del componente è un orologio. Il componente in Windows Form e anche nelle VCL possiede la proprietà Enabled, che è messa a false. Per attivare il suo funzionamento si deve quindi portare a true tale proprietà, altrimenti il timer non produce gli eventi ripetuti previsti. La proprietà Interval ha lo scopo di indicare l’intervallo di tempo in millisecondi ogni quanto viene richiamato l’evento del timer; essa ha lo stesso nome e scopo sia in Windows Form che in VCL. Ovviamente anche il Timer ha una proprietà Name per dare ad esso uno specifico nome. Per i componenti senza visibilità sull’interfaccia non hanno senso le proprietà Top, Left, Width ed Height. PictureBox (Windows Form) / TImage (VCL) Nel progettino in C# cui si doveva indovinare il numero segreto generato dal computer, abbiamo fatto uso di due PictureBox. Questo componente è utilizzato in Windows Form per visualizzare immagini sulla form stessa. Nel nostro caso abbiamo caricato l’immagine tramite la proprietà Image (Windows Form). Poi abbiamo imposto all’immagine stessa di assumere le dimensioni stesse del controllo effettuando una operazione di ridimensionamento / cambio delle proporzioni , detta strech. Questa operazione è attivata in questo controllo dalla proprietà SizeMode messa a StrechImage (noermalmente essa è a Normal). In questo modo abbiamo costretto l’immagine originale a ridimensionarsi fino a essere completamente visibile nel controllo. Nel caso di C++ Builder si può utilizzare un componente del tutto equivalente detto TImage (sezione dei componenti aggiuntivi). Il componente viene ridimensionato e posizionato, poi con la proprietà Picture sarà possibile caricare l’immagine voluta e visualizzarla. La proprietà Strech del controllo effettua lo strech dell’ immagine caricata se posta a true. La proprietà Visibile, permette di regolare la visibilità dell’immagine caricata, senza scaricarla dal controllo. Box di messaggio Non sono dei veri componenti, ma sono delle particolari form (di solito che appaiono in modalità modale4), atte a mostrare messaggi all’utilizzatore del programma (grafico). In questa sezione, in base a quanto utilizzato anche nei progettini fin qui affrontati, considereremo solo box di messaggio con un solo pulsante di conferma (Ok), nelle quali non essendoci alternative, non si pone il problema di comprendere quale pulsante sia stato premuto prima di chiudere la form di messaggio. 4 Una form è in modalità modale, se essa, una volta apparsa, è l’unica form del programma su cui può operare l’utente. Lo stato del programma, in background, resta “congelato”, in quanto l’utente non può accedere a nessuna delle funzionalità delle form in background finchè non chiude la form principale. Pagina 11
In Visual C# si producono con metodi cha appartengono ad una apposita classe MessageBox, preposta a generare tali form in molte forme e varianti. Il metodo che viene usato per produrre box di messaggio è lo Show, che a seconda del numero di parametri indicati produce finestre con caratteristiche diverse. Ad esempio l’istruzione: MessageBox.Show("Semplice messaggio", "Titolo"); crea una semplice MessageBox con solo messaggio e titolo, mentre la specifica di alcuni altri parametri consente di avere delle box con tutte le caratteristiche: MessageBox.Show("Semplice messaggio", "Titolo",MessageBoxButtons.OK, MessageBoxIcon.Information); Da notare che i valori di combinazioni di pulsanti e delle icone sono propri di apposite enumerazioni MessageBoxButtons che contiene diversi possibili valori quali Ok, OkCancel, YesNo, ed altri e MessageBoxIcon, che contiene costanti che definiscono il possibile tipo di icona, quali Information, Question, Warning ed altri. In C++ Builder sono utilizzate due funzioni VCL per produrre delle finestre di messaggio: ShowMessage – Crea una form con il solo pulsante Ok e una scritta esplicativa. La form di messaggio non ha icona ed il titolo non è regolabile. Ha un solo parametro, ossia il testo da scrivere. ShowMessage(“Questo e’ il messaggio”); MessageDlg – Permette di creare form di messaggio più articolate e con più elementi regolabili, tra cui un icona, il numero e tipo di pulsanti. Ha 5 parametri: o Messaggio o Icona (del tipo di messaggio) o Pulsanti da visualizzare Il quarto parametro relativo all’help contestuale, per scopi comuni, viene di solito messo a 0. Ad esempio il comando C++ Builder: MessageDlg("Messaggio da comunicare",mtInformation,TMsgDlgButtons()
viene utilizzata direttamente. Il metodo acquisisce come parametro il valore originario e rende un risultato che è il tipo di valore desiderato. Le conversioni, in questo caso sono effettuate da apposite funzioni VCL StrToInt(…) e viceversa IntToStr(…) preposte a convertire interi con stringhe e viceversa. Nella libreria VCL sono a disposizione numerose funzioni per effettuare conversioni quali StrToDate e DateToStr o StrToFloat e FloatToStr, ed altre. Gestione degli errori in C# e C++ Builder In alcuni listati abbiamo visto esempi di utilizzo di operazioni dotate di controllo su eventuali errori dovessero accadere durante l’esecuzione del codice. In particolare un esempio di semplice controllo di errore è facilmente applicabile al nostro programma che effettua la somma, riportato nei primi paragrafi di questa dispensa. In particolare il punto dove ovviamente potrebbero accadere delle situazioni di errore sono le conversioni dei valori letti dalle box di testo, ove l’utente ha inserito i due addendi. Tali conversioni sono da alfanumerico a numerico (abbiamo presunto i numeri siano interi). Due sono i possibili motivi di errore: L’utente non inserisce alcun dato L’utente inserisce dati non convertibili (ad. es. la stringa “abc” o altra) in un numerico intero In ambiente .NET questa situazione produce subito una eccezione che viene segnalata da una apposita finestra mentre il programma stà girando. Una cosa simile con analoga modalità avviene quando l’eseguibile C++ Builder incorre in un errore di conversione. In questi casi però il motivo della situazione di errore non viene esplicitato, e quindi è difficile capire cosa sia successo e quale sia la causa effettiva di errore. In questo caso si può decidere di realizzare una gestione custom dell’errore stesso che aiuti a comprendere con più precisione quale sia la causa del problema e a segnalarlo all’utente in modo semplice. Il controllo di errore sia in C# che in C++ viene fatto attraverso il costrutto sintattico try….catch…. Nella parte try si mettono le istruzioni da controllare, ossia si controlla se esse producano errori, mentre nella parte catch, oltre ad un filtro sulla tipologia/e di errore “catturata”, si predispongono le operazioni che devono essere svolte quando l’errore si verifica ed è del tipo previsto dalla specifica istruzione catch. Ad esempio per controllare errori di conversione relativi ai valori inseriti nelle box “Addendo 1” e “Addendo 2” del programma somma. Le conversioni normalmente effettuate in condizioni di dati corretti possono viceversa fallire, e quindi produrre errori di run-time. A questo punto un frammento di codice del seguente tipo può gestire qualunque errore legato al problema degli input errati: int n1 = 0, n2 = 0, ris; bool errore = false; try { n1 = Convert.ToInt32(txtAdd1.Text); n2 = Convert.ToInt32(txtAdd2.Text); } catch (FormatException fe) { MessageBox.Show("Valori degli addendi non adeguati.", " - Errore - "); errore = true; } if (!errore) { ris = n1 + n2; txtRisultato.Text = Convert.ToString(ris); Pagina 13
} In pratica il blocco try / catch entra in azione qui per motivi di dati non convertibili, ed allora viene visualizzata una box di messaggio, oltre a non eseguire il codice successivo, ossia quello che effettuerebbe la somma (ma non in questo caso mancando i dati). FormatException è il tipo di errore intercettato, e questa eccezione viene prodotta quando vi sono problemi a convertire i dati di input verso il tipo intero previsto. Con una metodica del tutto simile si può affrontare il problema di gestire analoghi errori in C++ Builder, tramite un controllo di errore gestito anche da apposite classi VCL. Con una logica del tutto simile alla precedente il codice C++ Builder è: int n1, n2, ris; bool errore = false; try { n1 = StrToInt(edtAdd1->Text); n2 = StrToInt(edtAdd2->Text); } catch (EConvertError &e) { ShowMessage("Dati inseriti non congruenti con l'operazione."); errore = true; } if (! errore) { ris = n1 + n2; edtRisultato->Text = IntToStr(ris); } Come è possibile vedere la logica dei due linguaggi è del tutto simile a parte qualche dettaglio sintattico. Anche qui la parte che controlla se ci sono errori è il try e c’è l’attivazione del codice nella parte catch se l’errore è della tipologia della classe indicata come parametro del catch. Il puntatore ad oggetto e, permette di accedere ad alcune informazioni proprie dello specifico errore accaduto. In questo caso la tipologia di eccezione corretta da usare è EConvertError. Si tratta di una classe preposta a gestire errori di conversione, essa è una tipologia di errore la cui gestione è prevista dalle librerie VCL. Altre classi di errore VCL sono elencate in: http://docwiki.embarcadero.com/RADStudio/Tokyo/en/VCL_Exception_Classes Pagina 14
Puoi anche leggere