lunedì 28 giugno 2010

Aggiungere la piattaforma JDK a NetBens IDE

Se avete seguito l'installazione della piattaforma JDK è giunto adesso il momento di aggiungerla a NetBeans IDE. Vi ricordo, infatti, che se siete su Ubuntu il sistema operativo ha e usa di default open-jdk (la versione open-source di JDK, creata per risolvere alcuni problemi sulle licenze d'uso). Avviamo NetBeans IDE, da riga di comando scrivendo netbeans nel terminale oppure dal menu delle applicazioni di Xubuntu (l'installazione di NetBeans IDE crea un collegamento all'applicazione nel menu "Sviluppo"). Cliccate sul menu "Tool", e selezionate la voce "Java Plattform":


Il riquadro rosso fa notare la presenza di open-jdk, usato di default da NetBeans IDE. Cliccate sul bottone "Add Plattform" e navigate nel filesystem fino a raggiungere la cartella in cui è stato installato JDK:


Per andare avanti premete sul bottone "Next". La prossima schermata vi chiede di dare un nome alla piattaforma:


Se avete scaricato anche la documentazione per la piattaforma è il momento di indicarne il path nell'area di input preceduta dall'etichetta "Plattform Javadoc". Cliccate su "Finish" per concludere l'aggiunta, la piattaforma JDK è adesso nota a NetBeans IDE che tuttavia continua a usare open-jdk di default.


Nelle proprietà di ogni progetto è adesso possibile indicare la piattaforma da usare. Se volete usare di default JDK editate il file che si trova nella cartella /etc/netbeans.conf. Dovete modificare la riga:

netbeans_jdkhome="/usr/lib/jvm/java-6-openjdk"

in maniera tale da far puntare la variabile netbeans_jdkhome alla cartella di JDK. Attenzione, questa operazione trasferisce la piattaforma di default da open-jdk a JDK (eliminando open-jdk dalla lista delle piattaforme disponibili). Se volete continuare a usare in seguito anche open-jdk vi consiglio allora di segnare il path che punta alla cartella di open-jdk e di aggiungerla in un secondo momento come nuova piattaforma. Ripetendo i passaggi visti sopra. Se sviluppate applicazioni Java è preferibile farlo con JDK!

Installazione di JDK su Linux

Quella che segue è la procedura suggerita da SUN Microsystems sulle pagine di supporto all'installazione del noto ambiente di sviluppo: Java Development Kit (JDK). L'ambiente viene distribuito attraverso due tipologie di file: un pacchetto rpm per le distribuzioni Linux che sanno già come trattare questo formato (come Fedora, SuSe e Red Hat) e un file binario più generico per tutte le altre distribuzioni Linux.
In questo articolo ci concentreremo proprio su quest'ultima tipologia di file. Sun Microsystems distribuisce i tipi di file detti sopra con dei nomi strutturati in un preciso modo. Nel caso del file binario, il nome del file da scaricare ha la seguente struttura: jdk-6u-numero_versione-linux-i586.bin. Trovate il file in questa pagina. Scaricato? Il primo passaggio che ci viene chiesto dalle note di installazione, oltre al donwload del file, è la verifica delle sue dimensioni. Possiamo segnare questo parametro nella pagina che precede l'operazione di download. Inutile procedere, quindi, con le successive istruzioni se il file non rispetta le dimensioni indicate in precedenza (detto in altre parole, il download è incompleto!). Prima di eseguire il file assicuratevi di aver dato allo stesso i permessi per l'esecuzione con:

chmod a+x jdk-6u-numero_versione-linux-i586.bin

Spostate il file nella directory in cui volete installare JDK. Attenzione, il file è eseguibile da qualsiasi utente ma solo l'utente root è abilitato a scrivere in certe cartelle del filesystem! Pertanto, se non disponete dei permessi in scrittura nel path inizialmente scelto si consiglia di installare JDK nella propria home. Per spostare il file binario potete usare il comando mv jdk-6u-numero_versione-linux-i586.bin /CARTELA_INSTALLAZIONE (eventualmente preceduto da sudo se non si hanno i permessi in scrittura nella cartella di destinazione).
L'esecuzione del file binario può avvenire sia dalla directory di lavoro corrente che da quella che ospita il file. Se ci troviamo nella cartella che ospita il file (spostato, ad esempio, in precedenza) e raggiunta con il comando cd /CARTELLA_INSTALLAZIONE è allora possibile eseguire il file binario con:

./jdk-6u-numero_versione-linux-i586.bin

Ci verrà proposta la licenza che regola l'utilizzo del prodotto, se siamo interessati a continuare l'installazione non ci resta che accettare. JDK verrà installato, dopo qualche minuto, in una cartella dal nome jdk1.6.0_numero_versione all'interno della cartella che ospita il file binario. L'ambiente appena installato può essere adesso utilizzato nei vari IDE di sviluppo (ad esempio NetBeans IDE ed Eclipse). Per configurare JDK in NetBeans IDE date uno sguardo a questa pagina.

sabato 26 giugno 2010

Un ripasso di SQL e MySQL

L'informazione è ormai manipolata in ogni contesto e negli ultimi anni si è affidata sempre più a strumenti informatici. La raccolta e la manipolazione dell'informazione è resa possibile grazie all'uso di database che in ambito informatico viene molto spesso chiamato DBMS: database management system. Nel corso degli anni sono state introdotte diverse strutture per DBMS: gerarchico, reticolare, relazionale, ad oggetti e semantico. In questo ripasso ci occuperemo di un DBMS relazionale: MySQL.
MySQL è un DBMS distribuito con licenza GPL, chiunque può accedere al codice sorgente del DBMS per apportare modifiche. In un database relazionale l'informazione viene memorizzata sotto forma di tabelle, oguna di queste può poi essere messa in relazione con altre tabelle del database. MySQL si basa sul noto modello client/server e prevede pertanto un'interfaccia di tipo client ed una di tipo server. L'interfaccia che MySQL offre di default al programmatore è a riga di comando, chi vuole può in ogni caso installare quella grafica.
Il client interroga o comanda il server (se ha i permessi per farlo) affinchè quest'ultimo restituisca l'informazione cercata (se presente nel database) oppure aggiunga al database una nuova informazione. L'interrogazione di un database (sia per la ricerca dei dati che per la loro immissione), detta query, avviene con un opportuno linguaggio (standard) noto con il nome di SQL (Struct Query Language). Per interagire con il server MySQL bisogna per prima cosa lanciare il daemon. Vediamo come farlo con l'Aspire One (che usa come sistema operativo di default Linux Linpus Lite, le istruzioni per l'avvio del server e client MySQL si adattano comunque a ogni sistema operativo Linux-like):

[user@localhost ~]$ sudo service mysqld start
Starting MySQL: [ OK ]
[user@localhost ~]$

Altri possibili comandi sono: stop (per fermare il daemon) e restart (per riavviare il daemon). L'interfaccia client viene invece avviata con il comando:

[user@localhost ~]$ sudo mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 27
Server version: 5.0.45 Source distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>

Il prompt è ora in attesa di comandi. Se vogliamo ad esempio conoscere i nomi dei database che di default si trovano presso il server MySQL va digitato questo comando:

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| test |
+--------------------+
3 rows in set (0.00 sec)

mysql>

Per selezionare un database digitiamo:

mysql> use test;
Database changed
mysql>

Prima ancora di vedere come creare database e tabelle, diamo ora uno sguardo ai tipi di dati che MySQL offre al programmatore per descrivere la propria realtà di riferimento.

Tipi di dati numerici
MySQL offre, per i numeri interi, questi tipi di dati:
  • TINYINT, occupa 1 byte;
  • SMALLINT, occupa 2 byte;
  • MEDIUMINT, occupa 3 byte;
  • INT, occupa 4 byte;
  • BIGINT, occupa 8 byte;
Per i numeri decimali, invece:
  • FLOAT, occupa 4 byte;
  • DOUBLE, occupa 8 byte;
  • DECIMAL(M,D), occupa M+2byte;
Il tipo DECIMAL permette di specificare con M e D, rispettivamente, il numero totale delle cifre che formano l'intero numero decimale e il numero di cifre per la parte decimale. I tipi di dati appena visti possono prevedere o meno delle opzioni. Con l'opzione UNSIGNED, ad esempio, si indica al server MySQL che l'attributo in questione non può avere valori negativi. Con l'opzione ZEROFILL si indica al server MySQL di allineare i numeri (in verticale) di un attributo riempiendolo con tanti zeri. Con l'opzione AUTOINCREMENT si imposta per l'attributo di una tabella una particolare proprietà: ad ogni istanza dello stesso il valore dell'attributo viene incrementato di un'unità.

Tipi di dati per testo
Per i tipi di dato orientati alla gestione del testo, ossia per le stringhe, MySQL prevede due utili tipi:
  • CHAR(M), occupa M byte;
  • VARCHAR(M), occupa M byte;
L'occupazione (fissa) in memoria viene specificata dal programmatore. Gli attributi di una tabella descritti dal tipo CHAR occupano in memoria uno spazio pari ad M byte. Al contrario invece, gli attributi di una tabella descritti dal tipo VARCHAR occupano un numero di byte variabile che al più può essere di M byte. In altre parole, con VARCHAR l'occupazione in memoria dell'informazione (ovvero della stringa in questo caso) varia a seconda dell'occorrenza.
I tipi di dati appena visti consentono di inserire in un database stringhe non più lunghe di 255 caratteri. Se tale limite non è sufficiente al nostro progetto possiamo allora adoperare altri tipi di dati come: BLOB e TEXT.

Tipi di dati per le date
L'informazione molto spesso deve poter trattare date e ore del giorno. A tale proposito MySQL offre due tipologie di dati, quelli orientati appunto alle date e quelli orientati esclusivamente ad una parte della data. Per la gestione di date complete (che comprendono quindi gli attributi: anno, mese, giorno, ora,minuto e secondo) si può fare riferimento ai tipi: TIMESTAMP (che occupa 14 byte) e DATETIME (che occupa 8 byte). Per la gestione parziale di una data si può invece fare riferimento ai tipi: DATE, TIME e YEAR.
Per il tipo TIMESTAMP bisogna considerare il seguente formato: AAAAMMGGHHMMSS. Passando a TIMESTAMP un parametro per modificare l'occupazione in byte del suddetto formato se ne modifica allora il contenuto. Ad esempio, con TIMESTAMP(12) vado ad escludere gli ultimi 2 byte, quelli che trattano cioè i secondi, e modifico in questo modo il formato: AAAAMMGGHHMM. Ancora, con TIMESTAMP(10) vado ad escludere gli ultimi 4 byte, quelli cioè che trattano i secondi e i minuti, e modifico in questo modo il formato: AAAAMMGGHH.
Se non siamo interessati per intero alla data di un evento possiamo allora usare il tipo DATE (che occupa 3 byte). La restante parte della data, quella che si occupa delle ore, dei minuti e dei secondi, è invece gestita dal tipo TIME (che occupa 3 byte).

DDL, data definition language
Il DDL è il linguaggio usato per definire gli schemi logici (ed eventualmente le autorizzazioni per l'accesso ai dati). Esso si fonda essenzialmente su tre parole chiavi: create (creare), drop (cancellare) e alter (modificare). La parola chiave create permette di creare oggetti nella base di dati:

create table;
create domain;
create view;
create constraint;

Per la creazione di un database:

mysql> create database segreteria;
Query OK, 1 row affected (0.00 sec)

mysql>

Per la creazione di tabelle si ricorre al comando create table. Ecco un esempio:

mysql> create table studente(
-> matricola varchar(15),
-> nome varchar(20),
-> cognome varchar(20),
-> nascita date);
Query OK, 0 rows affected (0.46 sec)

mysql>

In SQL ogni istruzione termina con il carattere ;. Il carattere ,, invece, viene usato per separare la descrizione di una colonna da quella successiva. Al comando create table deve seguire il nome da assegnare alla tabella. La descrizione dei campi che compongono la tabella deve avvenire all'interno delle parentesi ( e ). I campi dati sono specificati da un nome e dal tipo che meglio li rappresenta. I vincoli da assegnare ad un campo dati vengono specificati subito dopo il tipo se essi riguardano esclusivamente il campo stesso, oppure su una riga a parte se interessano più campi dati della tabella.

Valori di default per i tipi di dati
In alcuni casi può essere utile assegnare ad un tipo di dato un valore di default da usare qualora il valore, in fase di immissione, non fosse specificato dall'utente. Quando si vuole seguire questa strada occorre allora usare la parola chiave default e far seguire dopo di questa il valore di default, ecco un esempio:

mysql> create table studente(
-> matricola varchar(15),
-> nome varchar(20),
-> cognome varchar(20),
-> nascita date,
-> esami tinyint default 0);
Query OK, 0 rows affected (0.27 sec)

mysql>

Vincoli intrarelazionali
Sono vincoli (o condizioni) che coinvolgono una sola relazione e che devono essere verificati ad ogni istanza della base di dati, ecco un elenco:
  • not null, indica che il valore nullo non è ammeso come valore dell'attributo;
  • unique, impone che i valori dell'attributo all'interno della tabella siano unici. Pertanto, righe differenti di una tabella non possono avere gli stessi valori per quell'attributo (per il valore null si fa invece un'eccezione);
  • primary key, si tratta di un vincolo che è possibile esprimere in tabella una sola volta poichè identifica la chiave primaria per la tabella stessa. Si esprime sulla riga dell'attributo oppure su una riga separata nel caso in cui la chiave primaria è composta da più attributi.
Rivediamo, allora, l'esempio precedente adoperando ora i vincoli intrarelazionali appena visti:

mysql> create table studente(
-> matricola varchar(15),
-> nome varchar(20) not null,
-> cognome varchar(20) not null,
-> nascita date,
-> esami tinyint default 0,
-> primary key(matricola,cognome,nome));
Query OK, 0 rows affected (0.24 sec)

mysql>

All'interno di schemi scritti, la primary key viene identificata dall'attributo sottolineato, ecco un esempio:

studente(matricola, nome, cognome, nascita, esami)

Vincoli interrelazionali
Sono vincoli che coinvolgono più relazioni creando un legame tra i valori di un attributo della tabella corrente (detta tabella interna) e i valori di un attributo di un'altra tabella (detta tabella esterna). Il valore di un attributo alla quale si fa riferimento deve essere almeno unique (molto spesso accade che questo valore è primary key per la tabella esterna e quindi è anche unique, una chiave primaria è infatti anche unica nella tabella!).

mysql> create table studente(
-> nome varchar(20),
-> cognome varchar(20) not null,
-> matricola char(6) primary key);
Query OK, 0 rows affected (0.01 sec)

mysql> create table esame(
-> studente char(6) references studente(matricola),
-> voto smallint not null check((voto>=18) AND (voto<=30)), -> corso varchar(30) primary key);
Query OK, 0 rows affected (0.17 sec)

mysql>

Politiche di reazione
Cosa deve fare il database quando il sistema rileva una violazione di un vincolo? E' possibile assegnare al sistema alcune politiche di reazione non appena si verifica la violazione di un vincolo. La violazione di un vincolo, ad esempio, può avvenire cancellando o aggiornando un vincolo. Di default si assegna la politica no action ad un vincolo, se ciò deve invece essere modificato o impedito si ricorre a istruzioni così strutturate:

on delete|update cascade|set null|set default| no action

dove con:
  • cascade, il valore viene riportato su tutte le righe della tabella esterna;
  • set null, si assegna il valore null all'attributo referente;
  • set default, si assegna il valore di default all'attributo referente;
  • no action, l'azione di modifica o cancellazione non viene consentita;

Drop e alter
Questo comando permette di rimuovere componenti da un database. Tale comando in genere può non funzionare immediatamente. Il sistema infatti (la logica data a MySQL) chiede all'utente di svuotare prima la tabella, solo dopo averla svuotata può infatti essere cancellata. Questo discorso si applica anche a un database: prima si svuotano e cancellano le tabelle poi si cancella il databate!

mysql> drop table esame;
Query OK, 0 rows affected (0.00 sec)

mysql>

Nell'esempio il comando riesce proprio perché la tabella esiste ma è vuota! Il comando alter, invece, permette di modificare domini e schemi di tabelle.

DML, data manipulation language
L'informazione, una volta inserita nel database, va cercata e eventualmente elaborata. In questa sezione ci occuperemo dell'interrogazione di un database. Riporto qui di seguito gli esempi visti a lezione, per alcuni di questi faremo riferimento al seguente schema logico:

impiegato(nome, cognome, dipart, ufficio, stipendio, città)
dipartimento(nome, indirizzo, città)

1. Estrarre lo stipendio degli impiegati di cognome "Rossi":

select stipendio
from impiegato
where cognome='Rossi'

2. Estrarre tutte le informazioni relative agli impiegati di cognome "Rossi":

select *
from impiegato
where cognome='Rossi'

3. Estrarre lo stipendio mensile dell'impiegato che ha cognome "Bianchi":

select stipendio/12
from impiegato
where cognome='Bianchi'

Questo perché nella clausola select possono comparire generiche espressioni sul valore degli attributi di ciascuna riga selezionata.

4. Estrarre i nomi degli impiegati e le città in cui lavorano:

select I.nome, I.cognome, D.città
from impiegato as I,dipartimento as D
where I.dipart=D.nome

L'operatore punto identifica alla sua sinistra le tabelle da cui vengono estratti gli attributi (indicati alla destra del punto). Una tabella può essere rinominata con un opportuno alias preceduto dalla parola chiave as (che può anche essere omesso). In questo esempio la clausola select opera sul prodotto cartesiano delle tabelle in essa elencate e separate dal carattere ,. Nella clausola where in tal caso si specifica la condizione che lega le due tabelle.

5. Estrarre il nome e il cognome degli impiegati che lavorano nell'ufficio 20 del dipartimento di amministrazione:

select nome, cognome
from impiegato
where ufficio=20 and dipar='amministrazione'

Nella clausola where sono possibili gli operatori di relazione "=", ">", "<", "<=" e ">=" oltre a quelli logici and, or, e not. L'ordine con cui considerare tali operatori va eventualmente indicato con opportune parentesi se risulta essere diverso da quello previsto di default.

6. Estrarre i nomi e cognomi degli impiegati che lavorano nel dipartimento amministrazione o nel dipartimento produzione:

select nome, cognome
from impiegato
where dipart='amministrazione' or dipart='produzione'

7. Estrarre i nomi propri degli impiegati di cognome "Rossi" che lavorano nei dipartimenti amministrazione e produzione:

select nome
from impiegato
where cognome='Rossi' and (dipart='amministrazione' or dipart='produzione')

8. Estrarre gli impiegati che hanno un cognome che ha una "o" in seconda posizione e finisce per "i":

select *
from impiegato
where cognome like '_o%i'

L'operatore like permette un confronto di stringhe con stringhe in cui compaiono caratteri speciali. Il carattere "_" indica la possibilità di un qualsiasi carattere. Il carattere "%" indica l'occorrenza di una qualsia stringa.

9. Estrarre le città delle persone il cui cognome è "Rossi", presentando eventualmente più volte lo stesso valore di città:

persona(CodFiscale, nome, cognome, città)

select città
from persona
where cognome='Rossi'

10. Estrarre le città delle persone con cognome "Rossi" facendo comparire ogni città al più una sola volta:

persona(CodFiscale, nome, cognome, città)

select distinct città
from persona
where cognome='Rossi'

Per elimmnari i duplicati di un valore di un campo si fa procedere l'attributo dalla parola chiave distinct.

11. Estrarre il contenuto della tabella automobile ordinandolo in base alla marca e al modello:

automobile(targa, marca, modello, nropatente)

select *
from automobile
order by marca desc, modello

L'SQL permette di specificare come ordinare le righe del risultato di una interrogazione tramite la clasuola order by, che precede il nome dell'attributo, e facendo quindi seguire lo stesso attributo dalla parola chiave asc o desc.

12. Estrarre i nomi degli impiegati e le città in cui lavorano:

select I.nome, I.cognome, D.città
from impiegato as I join dipartimento as D on I.dipart=D.nome

Esiste una sintassi alternativa per la specifica dei join che permette di distinguere le condizioni dell'interrogazione da quelle di join. Usando questa sintassi la condizione che lega le tabelle non compare nella clasuola where.

13. Estrarre i guidatori con le automobili loro associate, mantenendo nel risultato anche i guidatori senza automobile:

automobile(targa, marca, modello, nropatente)
guidatore(nome, cognome, nropatente)

select distinct città
from guidatore G left join automobile A on (g.nropatente=A.nropatente)

Esistono diversi tipi di join: inner join, right outer join, left outer join e full outer join. L'outer join effettua un join mantenendo nel risultato tutte le righe di una tabella. Il left join fornisce come risultato il join esteso con le righe della tabella che compare a sinistra. Il right join fornisce come risultato il join esteso con le righe della tabella che compare a destra. Il full join restituisce il join interno esteso con le righe escluse di entrambe le tabelle.

14. Estrarre tutti i guidatori e tutte le auto, mostrando tutte le relazioni esistenti tra di essi:

select nome, cognome, G.nropatente, targa, marca, modello
from guidatore as G full join automobile as A on (G.nropatente=A.nropatente)

15. Estrarre il numero di impiegati del dipartimento produzione:

select count(*)
from impiegato
where dipart='produzione'

count(*) è un operatore in grado di contare il numero di righe che superano il filtro imposto dalla clausola where.

16. Estrarre il numero di diversi valori dell'attributo stipendio fra tutte le righe della tabella impegato:

select count(distinct stipendio)
from impiegato

17. Estrarre gli stipendi minimo, massimo e medio fra quelli di tutti gli impiegati:

select min(stipendio), max(stipendio), avg(stipendio)
from impiegato

18. Estrarre il massimo stipendio tra quelli degli impiegati che lavorano in un dipartimento con sede a Milano:

select max(stipendio)
from impiegato as I, dipartimento as D
where I.dipart=D.nome and città='Milano'

19. Estrarre la somma degli stipendi di tutti gli impiegati dello stesso dipartimento:

select dipart, sum(stipendio)
from impiegato
group by dipart

L'operatore aggregato sum può essere applicato ad un gruppo di righe mediante l'uso della clausola group by. Tale clausola ammette come argomento un insieme di attributi sicché la query raggrupperà le righe che possiedono effettivamente gli stessi valori per quell'attributo.

20. Estrarre i dipartimenti per cui la media degli stipendi degli impiegati che lavorano nell'ufficio 20 è superiore a 25 mila euro:

select dipart
from impiegato
where ufficio='20'
group by dipart
having avge(stipendio) > 25

21. Estrarre i nomi ed i cognomi di tutti gli impiegati, ad eccezione di quelli appartenenti al dipartimento amministrazione e mantenendo i duplicati:

select nome
from impiegato
where dipartimento<>'amministrazione'

union all

select cognome
from impiegato
where dipartimento<>'amministrazione'

22. Estrarre gli impiegati che lavorano in dipartimenti situati a Firenze:

select *
from impiegato
where dipartimento = any (select nome
from dipartimento
where città='Firenze')

Questo esempio ci permette di introdurre le query nidificate. In tal caso, una query interna seleziona il nome del dipartimento (situato a Firenze) mentre quella esterna confronta il risultato dell'interrogazione con l'attributo dipartimento della tabella impiegato convalidando il risultato nel caso in cui esista in essa almeno un valore valido.

Inserimento di valori in una tabella
Il comando SQL per l'inserimento di nuovi valori in tabella è insert. Per l'inserimento dei valori occorre conoscere l'ordine degli attributi appartenenti alla tabella. Un modo per inserire nuovi valori è il seguente:

insert into impiegato('Mario','Rossi','produzione',20,25000,'Firenze')

Per modificare un valore già presente in tabella si adopera invece il comando update:

update impiegato
set stipendio=20000
where nome='Mario' and cognome='Rossi'


Cancellare valori in una tabella
L'eliminazione di un valore all'interno di una tabella va fatto con il comando delete from. Ecco un esempio:

delete from impiegato
where nome='Mario' and cognome='Rossi'

Se l'argomento della clausola where non viene specificato il comando cancellerà di default tutte le righe della tabella indicata. MySQL offre molte altre cose, a tale proposito vi segnalo il sito di riferimento presso cui rimediare il software e la relativa documentaziione: http://www.mysql.it/.

venerdì 25 giugno 2010

Java: componenti swing per le GUI

Una volta conosciuti i limiti e le caratteristiche di alcuni layout possiamo adesso dare uno sguardo ai componenti Swing per le GUI. Vi presenterò i componenti più usati. Trovate, come sempre, un elenco assai più lungo nella documentazione in linea messa a disposizione da SUN Microsystems.

Campi di testo
Per l'immissione del testo esistono essenzialmente due componenti Swing: JTestField e JTextArea. Si tratta di due classi che estendono la classe (astratta) JTextComponent ereditando, quindi, dalla stessa alcuni metodi come:
  • setText(): che riceve una stringa, come parametro, da aggiunge al componente;
  • getText(): che ritorna il testo inserito dall'utente nel componente;
  • setEditable(): che riceve un valore booleano come parametro affinchè si possa abilitare/disabilitare in scrittura il componente;
Ecco subito un esempio:

JTextField area1=new JTextField("Inserire un valore",15);

Esistono più versioni del costruttore JTextField, uno specifica con un numero intero il numero di colonne del componente, mentre un secondo costruttore (come quello usato nell'esempio) permette di specificare una stringa iniziale e il numero di colonne. Se il testo supera il numero di colonne previste quest'ultimo, allora, scorrerà sull'unica riga di input! Se invece vogliamo dare all'utente la possibilità di inserire un testo su più righe abbiamo allora bisogno di un'area di testo:

JTextArea area2=new JTextArea(5,15);

Dove i parametri passati indicano,rispettivamente, il numero di righe e il numero di colonne da assegnare al componente. Il solo uso di un componente JTextArea, ne sono sicuro, non soddisfa quasi mai ne l'utente ne il programmatore. Perchè? Se il testo eccede il numero di colonne il componente viene ridimensionato! Per fissare la sua dimensione e adagiare il testo al suo interno occorre aggiungere al componente un'utile barra di scorrimento con il seguente codice:

JTextArea area2=new JTextArea(5,15);
JScrollPane area2_con_barra=new JScrollPane(area2);


Esiste, infine, un secondo costruttore per il componente JTextArea che permettte di specificare una stringa iniziale da aggiungere al componente (vedere l'esempio successivo). Un metodo usato spesse volte con un componente JTextArea, per l'aggiunta di nuovo testo, è il metodo append. Attraverso questo metodo la strnga passata come parametro viene aggiunta in coda al testo già esistente nel componente!

public class Pannello_GUI extends JPanel {
   public Pannello_GUI() {
      this.setLayout(new BorderLayout());
      JPanel pannello_CENTER=new JPanel();
      JTextField area1=new JTextField("Inserire un valore",15);
      JTextArea area2=new JTextArea("Inserire una descrizione",5,15);
      JScrollPane area2_con_barra=new JScrollPane(area2);
      pannello_CENTER.add(area1);
      pannello_CENTER.add(area2_con_barra);
      this.add(pannello_NORTH,BorderLayout.CENTER);
   }
}


Un particolare componente JTextField è il componente JPasswordField che, come avrete sicuramente intuito, permette l'input di password o dati sensibili nascondendoli da sguardi indiscreti. Il costruttore permette di specificare una stringa iniziale e il numero di colonne da assegnare al componente. Ogni carattere lì digitato verrà sostituito da un carattere che farà da echo (solitamante un asterisco). Inoltre, se vogliamo modificare il carattere di echo possiamo invocare sul componente il metodo setEchoChar e passare a questo il nuovo carattere di echo! L'accesso al valore nascosto, invece, avviene con il metodo getPassword che ritorna un array di caratteri:

public class Pannello_GUI extends JPanel {
   public Pannello_GUI() {
      this.setLayout(new BorderLayout());
      JPanel pannello_NORTH=new JPanel();
      JPasswordField area1=new JPasswordField("",15);
      area1.setEchoChar('*');
      pannello_NORTH.add(area1);
      this.add(pannello_NORTH,BorderLayout.CENTER);
   }
}

Label o etichette per i componenti
Finora ogni componente aggiunto al pannello dell'interfaccia grafica era privo di un riferimento utile a far capire all'utente cosa effettivamente scrivere nei campi dati. Per suggerire all'utente l'utilità di un campo dati si ricorre al componente JLabel:

public class Pannello_GUI extends JPanel {
   public Pannello_GUI() {
      this.setLayout(new BorderLayout());
      JLabel etichetta1=new JLabel("Password:");
      JPanel pannello_CENTER=new JPanel();
      JPasswordField area1=new JPasswordField("",10);
      area1.setEchoChar('*');
      pannello_CENTER.add(etichetta1);
      pannello_CENTER.add(area1);
      this.add(pannello_NORTH,BorderLayout.CENTER);
   }
}

Attenzione all'ordine con cui inserite i componenti!


Caselle per la scelta di opzioni
L'interfaccia Java, così avviene per i form html, offre all'utente la possibilità di effettuare una scelta di un input attraverso l'uso di caselle o checkbox. Una checkbox può avere un proprio significato, essere cioè indipendente da altre checkbox, oppure può appartenere a un gruppo di checkbox (in cui la selezione di una disabilita tutte le altre). A differenza dei precedenti componenti, le checkbox prevedono all'interno del costruttore una label da passare allo stesso componente (sotto forma di stringa). Ecco un esempio:

JCheckBox protocollo=new JCheckBox("Protocollo sicuro");

Per stabilire lo stato del componente si può chiamare su di esso il metodo isSelected (che ritorna true se il componente è selezionato, false se deselezionato). Se invece bisogna selezionare di default una checkbox si deve allora chiamare su di essa il metodo setSelected e passare, quindi, un valore booleano. Per un gruppo di checkbox va invece usato il componente ButtonGroup che permette di istanziare un componente in grado di integrare (attraverso il metodo add), sotto un unico gruppo, più checkbox (create questa volta attraverso JRadioButton):

ButtonGroup server=new ButtonGroup();
JRadioButton server1=new JRadioButton("Server Nro 1",true);
JRadioButton server2=new JRadioButton("Server Nro 2",false);
server.add(server1);
server.add(server2);

Al costruttore di JRadioButton occorre passare una label e un valore booleano. Attenzione, uno solo dei valori appartenenti al componente ButtonGroup dovrà avere il valore true!

public class Pannello_GUI extends JPanel {
   public Pannello_GUI() {
      this.setLayout(new BorderLayout());
      JLabel etichetta1=new JLabel("Password:");
      JPanel pannello_NORTH=new JPanel();
      JPasswordField area1=new JPasswordField("",10);
      area1.setEchoChar('*');
      pannello_NORTH.add(etichetta1);
      pannello_NORTH.add(area1);
      JPanel pannello_CENTER=new JPanel();
      JCheckBox protocollo=new JCheckBox("Protocollo sicuro");
      pannello_CENTER.add(protocollo);
      JPanel pannello_SOUTH=new JPanel();
      ButtonGroup server=new ButtonGroup();
      JRadioButton server1=new JRadioButton("Server Nro 1",true);
      JRadioButton server2=new JRadioButton("Server Nro 2",false);
      server.add(server1);
      server.add(server2);
      pannello_SOUTH.add(server1);
      pannello_SOUTH.add(server2);
      this.add(pannello_NORTH,BorderLayout.NORTH);
      this.add(pannello_CENTER,BorderLayout.CENTER);
      this.add(pannello_SOUTH,BorderLayout.SOUTH);
   }
}


Combo box
Con il componente JComboBox possiamo inserire in un pannello un menu attraverso cui selezionare un valore:

JComboBox server=new JComboBox();
server.addItem("Server N.ro 1");
server.addItem("Server N.ro 2");
server.addItem("Server N.ro 3");

Il metodo AddItem permette l'aggiunta di nuove voci all'interno del componente. L'elemento selezionato viene quindi recuperato attraverso la chiamata al metodo getSelectedItem. Se si vuole dare la possibilità di modificare una voce all'interno della lista (anche a runtime) occorre abilitare in scrittura il componente mediante il metodo setEditable (che accetta come parametro un valore booleano).

public class Pannello_GUI extends JPanel {
   public Pannello_GUI() {
      this.setLayout(new BorderLayout());
      JLabel etichetta1=new JLabel("Password:");
      JPanel pannello_NORTH=new JPanel();
      JPasswordField area1=new JPasswordField("",10);
      area1.setEchoChar('*');
      pannello_NORTH.add(etichetta1);
      pannello_NORTH.add(area1);
      JPanel pannello_CENTER=new JPanel();
      JCheckBox protocollo=new JCheckBox("Protocollo sicuro");
      pannello_CENTER.add(protocollo);
      JPanel pannello_SOUTH=new JPanel();
      JLabel etichetta2=new JLabel("Server:");
      JComboBox server=new JComboBox();
      server.setEditable(true);
      server.addItem("Server N.ro 1");
      server.addItem("Server N.ro 2");
      server.addItem("Server N.ro 3");
      pannello_SOUTH.add(etichetta2);
      pannello_SOUTH.add(server);
      this.add(pannello_NORTH,BorderLayout.NORTH);
      this.add(pannello_CENTER,BorderLayout.CENTER);
      this.add(pannello_SOUTH,BorderLayout.SOUTH);
   }
}


Menu
I menu a discesa caratterizzano da sempre gli ambienti e i programmi organizzati in frame. Si tratta di un componente indispensabile per alcune applicazioni, soprattutto quando non si vuole riempire eccessivamente il pannello utente. Ecco allora che conviene organizzare all'interno di un menu a discesa ogni comando che è possibile inviare al programma in esecuzione. La barra contenente un menu raggruppa sotto alcune voci principali i comandi e/o le funzionalità del programma e può, quindi, essere articolato in un o più sotto livelli di menu. La classica barra dei menu presente nei programmi Windows ne è un tipico esempio, lì solitamente troviamo una voce File, Edit, View etc... Per aggiungere una barra per il menu bisogna creare un oggetto JMenuBar:

JMenuBar menu=new JMenuBar();

che farà da contenitore a tutte le voci. Quindi bisogna aggiungere le voci principali aggiungendo in ognuna di queste una o più oggetti JMenuItem, attraverso il metodo add:

JMenu fileMenu=new JMenu("File");
JMenuItem apriFile=new JMenuItem("Apri file");
JMenuItem chiudiFile=new JMenuItem("Chiudi file");
JMenuItem esciFile=new JMenuItem("Esci");
fileMenu.add(apriFile);
fileMenu.add(chiudiFile);
fileMenu.add(esciFile);

Fatto ciò occorre aggiungere il singolo menu al contenitore dei menu, overro alla barra in alto dei menu con il comando:

menu.add(fileMenu);

Attenzione, la barra dei menu va aggiunta al frame che contiene i pannelli e non ai pannelli! Per questo motivo ho modificato leggermente la classe che descrive e dispone i componenti nel frame:

public class Pannello_GUI extends JPanel {
   public Pannello_GUI(Finestra finestra) {
      this.setLayout(new BorderLayout());
   JLabel etichetta1=new JLabel("Password:");
   JPanel pannello_NORTH=new JPanel();
   JPasswordField area1=new JPasswordField("",10);
   area1.setEchoChar('*');
   pannello_NORTH.add(etichetta1);
   pannello_NORTH.add(area1);
   JPanel pannello_CENTER=new JPanel();
   JCheckBox protocollo=new JCheckBox("Protocollo sicuro");
   pannello_CENTER.add(protocollo);
   JPanel pannello_SOUTH=new JPanel();
   JLabel etichetta2=new JLabel("Server:");
   JComboBox server=new JComboBox();
   server.setEditable(true);
   server.addItem("Server N.ro 1");
   server.addItem("Server N.ro 2");
   server.addItem("Server N.ro 3");
   pannello_SOUTH.add(etichetta2);
   pannello_SOUTH.add(server);
   JMenuBar menu=new JMenuBar();
   JMenu fileMenu=new JMenu("File");
   JMenuItem apriFile=new JMenuItem("Apri file");
   JMenuItem chiudiFile=new JMenuItem("Chiudi file");
   JMenuItem esciFile=new JMenuItem("Esci");
   fileMenu.add(apriFile);
   fileMenu.add(chiudiFile);
   fileMenu.add(esciFile);
   JMenu impostazioniMenu=new JMenu("Impostazioni");
   JMenuItem modificaImpostazioni=new JMenuItem("Modifica impostazioni");
   impostazioniMenu.add(modificaImpostazioni);
   JMenu infoMenu=new JMenu("Info");
   JMenuItem guidaInfo=new JMenuItem("Guida");
      infoMenu.add(guidaInfo);
      menu.add(fileMenu);
      menu.add(impostazioniMenu);
      menu.add(infoMenu);
   finestra.setJMenuBar(menu);
      this.add(pannello_NORTH,BorderLayout.NORTH);
   this.add(pannello_CENTER,BorderLayout.CENTER);
   this.add(pannello_SOUTH,BorderLayout.SOUTH);
   }
}


Termino qui questa breve presentazione di componenti per interfacce Java. Vorrei comunque ricordare, nuovamente, che i componenti fin qui visti non esauriscono l'intero set di componenti Swing. Per questo motivo invito gli utenti a cercare gli stessi, nonchè i metodi, all'interno della documentazione in linea (e nelle rispettive classi padre)!

martedì 22 giugno 2010

Java: gestione dei layout per le GUI

Le GUI, graphical user interface, svolgono l'importante compito dell'interfacciamento fra programma e utente. Java offre al programmatore, e indirettamente all'utente, numerosi componenti per l'interfaccia grafica. La libreria di riferimento è ancora una volta la libreria Swing di Java. Attraverso questa si possono istanziare bottoni, aree di testo, campi di testo per password, menu etc... Ancora prima di vedere come ciò può essere fatto dobbiamo necessariamente preoccuparci di un'importante questione, la gestione del layout.
Come andranno posizionati all'interno del frame i componenti dell'interfaccia Swing? Di default, Java utilizza un layout non sempre idoneo all'applicazione che abbiamo in mente. Questo, infatti, inserisce ogni componente al centro del frame, a partire dalla prima riga utile nel frame. Quando lo spazio per un nuovo componente non è sufficiente a contenere lo stesso sulla medesima riga, quest'utlimo viene dunque inserito su una riga a parte!



JButton buttonA=new JButton("A");
JButton buttonA=new JButton("B");
JButton buttonA=new JButton("C");
JButton buttonA=new JButton("D");
JButton buttonA=new JButton("E");
JButton buttonA=new JButton("F");
add(buttonA);
add(buttonB);
add(buttonC);
add(buttonD);
add(buttonE);
add(buttonF);

Il gestore di layout di flusso, quello usato di default da Java, permette l'allineamento dei componenti a destra o a sinistra del frame. La scelta può essere fatta invocando il metodo setLayout nel costruttore del pannello e passando allo stesso una delle due costanti FlowLayout.LEFT oppure FlowLayout.RIGHT. Ecco un esempio:

setLayout(new FlowLayout(FlowLayout.LEFT));

Esiste anche un costruttore per layout di flusso che permette di specificare oltre all'allineamento anche le distanze orizzontali e verticali fra i componenti dell'interfaccia. Per ulteriori informazioni consultate la documentazione in linea. Come dicevo poco fa non sempre questo layout può andare bene per la GUI che abbiamo in mente. Esiste allora un diverso gestore di layout, ossia il gestore di layout di bordi. Quest'ultimo, suddividendo il frame in più aree, permette l'aggiunta dei componenti in ognuna di esse.


this.setLayout(new BorderLayout());
JButton northButton=new JButton("Nord");
JButton westButton=new JButton("Ovest");
JButton centerButton=new JButton("Centro");
JButton centerButtonFlip=new JButton("Inverti");
JButton eastButton=new JButton("Est");
JButton southButton=new JButton("Sud");
add(northButton,BorderLayout.NORTH);
add(westButton,BorderLayout.WEST);
add(centerButtonFlip,BorderLayout.CENTER);
add(centerButton,BorderLayout.CENTER);
add(eastButton,BorderLayout.EAST);
add(southButton,BorderLayout.SOUTH);


L'immagine dovrebbe mostrare alcune importanti limitazioni di questo layout. La prima cosa che salta subito agli occhi è che i componenti vengono sì aggiunti nelle rispettive aree del frame ma vanno, purtroppo, ad occupare l'intero spazio! Ed ancora, osservando attentamente il codice scoprirete che all'interno di esso erano stati chiesti 2 bottoni al centro, nel frame ne appare uno solo! Questo perchè ogni componente aggiunto in una zona del frame sovrasta, se presente, un componente aggiunto in precedenza. Il problema può essere tranquillamente aggirato assegnando il componente in un pannello a parte e aggiungendo, quindi, lo stesso pannello al pannello con il layout!

this.setLayout(new BorderLayout());
JPanel northPanel=new JPanel();
JButton northButton=new JButton("Nord");
northPanel.add(northButton);
this.add(northPanel,BorderLayout.NORTH);
JPanel westPanel=new JPanel();
JButton westButton=new JButton("Ovest");
westPanel.add(westButton);
this.add(westPanel,BorderLayout.WEST);
JPanel centerPanel=new JPanel();
JButton centerButton=new JButton("Centro");
JButton centerButtonFlip=new JButton("Inverti");
centerPanel.add(centerButton);
centerPanel.add(centerButtonFlip);
this.add(centerPanel,BorderLayout.CENTER);
JPanel eastPanel=new JPanel();
JButton eastButton=new JButton("Est");
eastPanel.add(eastButton);
this.add(eastPanel,BorderLayout.EAST);
JPanel southPanel=new JPanel();
JButton southButton=new JButton("Sud");
southPanel.add(southButton);
this.add(southPanel,BorderLayout.SOUTH);


Direi che va decisamente meglio. Nell'esempio mostrato sopra ho quindi creato un pannello per ogni area o bordo. Ho poi aggiunto i componenti dell'interfaccia in questi pannelli e infine ho aggiunto gli stessi al frame, collocandoli nelle rispettive aree. Ciò funziona perchè di default, per un pannello, il gestore di layout è un gestore di layout di flusso! L'ultimo gestore di layout che vi presento permette di disporre i componenti dell'interfaccia utente secondo una griglia:

setLayout(new GridLayout(4,4,5,5));
JButton button1=new JButton("1");
JButton button2=new JButton("2");
JButton button3=new JButton("3");
JButton button4=new JButton("4");
JButton button5=new JButton("5");
JButton button6=new JButton("6");
JButton button7=new JButton("7");
JButton button8=new JButton("8");
JButton button9=new JButton("9");
JButton button0=new JButton("0");
JButton buttonSum=new JButton("+");
JButton buttonDiff=new JButton("-");
JButton buttonMul=new JButton("*");
JButton buttonDiv=new JButton("/");
JButton buttonCalc=new JButton("=");
JButton buttonCanc=new JButton("Canc");
add(button1);
add(button2);
add(button3);
add(buttonSum);
add(button4);
add(button5);
add(button6);
add(buttonDiff);
add(button7);
add(button8);
add(button9);
add(buttonMul);
add(buttonCanc);
add(button0);
add(buttonCalc);
add(buttonDiv);


L'ordine di aggiunta per i componenti ha dunque inizio a partire dalla prima cella in alto a sinistra. Il costruttore del layout permette di specificare il numero di righe e di colonne (i primi due parametri), se necessario è poi possibile indicare le distanze verticali e orizzontali, in pixel, che devono esistere fra i componenti (gli ultimi due parametri).

Aspire One, Linpus lite: conky, installazione e configurazione

Qualcuno usa "Conky"?
Si tratta di un monitor per risorse di sistema altamente configurabile. Il programma è facilmente installabile, nei repository è infatti presente la versione 1.6.1. Non proprio l'ultima ma comunque utile.

[user@localhost ~]$ sudo yum install conky

Non appena "yum" trova il pacchetto per l'installazione premete il tasto "y" per confermare l'installazione (altrimenti "n", per annullarla). A questa pagina trovate una lista delle variabili supportate da "Conky". E' con queste che dovrete descrivere il vostro widget, modificando il file "/etc/conky/conky.conf". Di default, dopo l'installazione, il file contiene già una configurazione. Questo è il contenuto del mio file "conky.conf":

#Collocazione dell'oggetto sul desktop
alignment top_right

#Sono permessi valori booleani ("true" oppure "false"), se "true" il processo verrà legato associato al desktop
background no

#Esprime la larghezza dei bordi in pixel
border_width 1

#Specifica il numero di campionamenti per la CPU da monitorare
cpu_avg_samples 2

#Colore usato di default (valido anche per i bordi)
default_color white

#Colore usato di default per le linee esterne
default_outline_color white

#Colore usato di default per l'effetto ombra (valido anche per i bordi)
default_shade_color white

#Abilita/Disabilita i bordi intorno al testo
draw_borders no

#Abilita/Disabilita i bordi intorno ai grafici
draw_graph_borders yes

#Disegna le linee esterne
draw_outline no

#Disegna l'effetto ombra
draw_shades no

#Usa i font XFT
use_xft yes

#Specifica il tipo di font da usare e la misura dei caratteri
xftfont Sans:size=10

#Tenta di usare la codifica UTF8
override_utf8_locale yes

#Specifica la distanza, in pixel, che deve esistere tra il bordo sinistro o destro dello schermo (a seconda dell'allineamento scelto)
gap_x 10

#Specifica la distanza, in pixel, che deve esistere tra il bordo superiore o inferiore dello schermo (a seconda dell'allineamento scelto)
gap_y 10

#Specifica la dimensione dell'intero oggetto in pixell
minimum_size 180 0

#Specifica il numero di campionamente per l'interfaccia di rete da seguire
net_avg_samples 2

#Usa il buffer
no_buffers yes

#Usa il doppio buffer (riduce sgradevoli effetti, può non funzionare a tutti)
double_buffer yes

#Abilita la stampa su una console
out_to_console no

#Crea una finestra
own_window yes

#Imposta il tipo di finestra da disegnare
own_window_class Conky

#Imposta all'oggetto l'effetto trasparenza
own_window_transparent yes

#Può essere impostato solo se own_windows è su "yes", specifica il tipo dell'oggetto
own_window_type desktop

#
own_window_hints undecorated,below,sticky,skip_taskbar,skip_pager

#Imposta la dimensione delle strisce (per i bordi)
stippled_borders 0

#Frequenza di aggiornamento
update_interval 1.0

#Decide se scrivere tutte informazioni in maiuscolo
uppercase no

#Aggiunge spazio intorno a certi oggetti, utile ad esempio se si nota un conflitto con lo sfonfo
use_spacer none

#Mostra il massimo valore nella scala dei valori
show_graph_scale no

#Mostra l'intervallo usato
show_graph_range no

#Descrizione dell'oggetto
TEXT
${alignc 20}${font Trebuchet MS:size=26}${time %H:%M}${font}
${alignc}${time %a %d %b %Y}

${color grey}CPU:${color} ${cpu cpu}% ${alignr}${alignr}${cpubar 8,80 cpu}
${color grey}RAM:${color} $memperc% ${alignr}${membar 8,80}
${color grey}SWAP:${color} $swapperc% ${alignr}${swapbar 8,80}
${color grey}SSD:${color} ${fs_free /root}/${fs_size /root} ${alignr}${fs_bar 8,80 /}

${color grey}ESSID: ${alignr}${color}${wireless_essid ath0}
${color grey}Qualità:${color} ${wireless_link_qual_perc ath0}% ${alignr}${wireless_link_bar 8,80 ath0}
${color grey}Indirizzo IP:${color}${alignr}${addr ath0}

${color grey}Download:${color} ${downspeedf ath0} KiB
${alignc}${downspeedgraph ath0 25,200}
${color grey}Upload:${color} ${upspeedf ath0} KiB
${alignc}${upspeedgraph ath0 25,200}

Ho anche commentato ogni riga, cercando di spiegare in questo modo l'utilità del comando. Aprite il file di configurazione con il comando "sudo mousepad /etc/conky/conky.conf", cancellate il contenuto e inserite (facendo copia e incolla) il codice mostrato sopra o quello da voi ideato. Non dimenticate di salvare (tasti "Ctrl" ed "s"), chiudete mousepad ed eseguite "Conky". Come? Date il comando "conky", il risultato dovrebbe essere qualcosa di simile:


Dimenticavo, dovete eseguire la modalità desktop per apprezzarne l'utilità.

lunedì 21 giugno 2010

Aspire One, il caldo si fa sentire

L'altro giorno ho comprato su ebay un cooling pad da mettere sotto l'Aspire One. Non siamo ancora alle temperature calde tipiche del mese di Luglio e Agosto ma ho pensato di aiutare il mio Aspire One a smaltire un po di calore accumulato. Ho però notato una cosa tipica di tutti i cooling pad in commercio che proverò a spiegare. Prendiamo in considerazione il nostro amato Aspire One, il flusso d'aria che dovrebbe raffreddare il processore viene all'occorrenza generato dalla ventola montata all'interno, proprio sopra la cpu. La rotazione della ventola è tale da aspirare l'aria da un lato, la grata più grande posizionata davanti l'Aspire One, e espellere quella calda attraverso la grata più piccola posizionata a lato (in mezzo alle prese per il monitor esterno e il cavo ethernet).


Il cooling pad in questione (ma, vedendo altre immagini in rete, funzionano tutti allo stesso modo) è questo qui:


Nell'immagine ho anche evidenziato con delle frecce la direzione del flusso generato dalle ventole. Secondo voi questa configurazione è corretta? Quando la ventola di raffreddamento dell'Aspire One è accesa il flusso della ventola sinistra del cooling pad si scontra con quello in uscita dall'Aspire One. Ho infatti notato che l'Aspire One in questo scenario fa più fatica a far scendere la temperatura! Se infatti stacco il cooling pad quando è accesa la ventola dell'Aspire One la temperatura scende prima!
Una situazione invece favorevole a questa configurazione è quella all'avvio del computer, quando cioè il processore ha ancora una temperatura bassa e la ventola di raffreddamento dell'Aspire One non si è ancora attivata. E' in questa circostanza che una porzione del flusso generato dal cooling pad riesce ad arrivare fino al processore e a portare qualche beneficio (ritardando l'accensione della ventola interna). Siccome ritengo che il calore in eccesso vada aspirato dall'Aspire One ho allora fatto una piccola modifica al cooling pad:


Ho invertito il flusso della ventola 1 montandola al contrario! L'altra possibilità che avevo era quella di invertire la polarità della tensione che alimenta quella ventola, direi che è assai più semplice smontarla e rimontarla al contrario. In questo modo, mentre la ventola 2 genera il flusso in entrata, la ventola 1 estrae il flusso di aria calda, aiutando quella interna (quando è attiva). E' importante far corrispondere la ventola 1 al di sotto della grata per il flusso in uscita, come mostrato in figura. L'Aspire One, ma anche altri computer, hanno spesso una grata inferiore troppo vicina al fondo della scrivania o del piano di appoggio (in rete si trovano anche tappi o piedi che tengono sollevato il computer di qualche centimetro). Per adesso basta, vedremo fra qualche giorno se tutto questo servirà. Cosa ne pensate?

sabato 19 giugno 2010

Linux e il software

L'informatica è fatta di molte sigle e termini ambigui! L'utente molto spesso non si sofferma sul reale significato di un termine e a mente ne definisce, quasi sempre, uno proprio. Il modo di ragionare potrebbe essere corretto ma come dicevo all'inizio non sempre giungiamo da soli alla definizione più ovvia.
Facciamo qualche esempio, mai sentito parlare di software free?
La traduzione del termine nella nostra lingua punta inevitabilmente a: software libero, e qui sono sicuro che in molti assoceranno questa parola anche al software gratis. Il problema è che in inglese la parola free significa sia libero che gratis, ed è proprio questa ambiguità a generare non pochi problemi.
Un software gratis, detto anche freeware, viene distribuito senza alcun compenso con o senza codice sorgente. Qui l'aspetto più importante è quello economico, nulla è dovuto se siamo interessati ad usare il software (che in molti casi è liberamente diplicabile e ridistribuibile) [2].
Un software libero, ed è questa è la giusta traduzione, è invece tutt'altra cosa! Una definizione rigorosa di software libero ci viene rilasciata da Richard Stallman, il fondatore dalla FSF (Free Software Foundation). Un software libero è da considerarsi tale se e solo se gode di queste proprietà:
  • Libertà 0: il programma può essere usato da tutti per qualsiasi scopo;
  • Libertà 1: il programma può essere studiato e modificato nel codice;
  • Libertà 2: il programma può essere copiato e distribuito per aiutare il prossimo;
  • Libertà 3: il programma migliorato va ridistribuito a tutta la comunità;
Il software libero, dunque, è una questione di libertà, non di prezzo [1].
E se ora vi direi di pensare alla parola open source?
Un software open source è un software che permette ai suoi utilizzatori di apportare modifiche e di studiarne il codice. Software open source vuol dire software a codice aperto. Tutto questo viene proposto per migliorare, nel tempo, il software stesso. Internet ha permesso al software open source di crescere molto rapidamente, annullando di fatto le distanze esistenti fra i vari programmatori.
La collaborazione, mediante l'accesso al codice sorgente, favorisce lo sviluppo del software che altrimenti, se portato avanti da pochi individui, risulterebbe assai più lenta. Open source, quindi, è più una metodologia di sviluppo per il software e osserva i seguenti principi di base:
  • Libertà di ridistribuire il software: l'utente che effettua la ridistribuzione del codice decide se farlo gratuitamente oppure dietro compenso;
  • Libero accesso al codice sorgente che definisce il programma;
  • Il software derivato dal codice sorgente del software stesso e quindi modificato va rilasciato sotto la stessa licenza;
  • Integrità del codice sorgente dell'autore;
  • Nessuna discriminazione contro gruppi o persone nel rilascio della licenza;
  • Nessuna discriminazione contro l'uso dell'applicazione;
  • La licenza deve essere distribuibile;
  • La licenza non può essere specifica per un prodotto;
  • La licenza non deve coinvolgere altri software;
  • La licenza deve essere tecnologicamente neutrale;
Maggiori dettagli sui principi sopra elencati possono essere ricercati in [3]. E' evidente che alcuni di questi principi hanno motivo di esistere solo dopo aver parlato delle licenze. Ogni software, anche quelli open source e free, viene lasciato sotto una particolare licenza. La licenza dice cosa è possibile fare con il software. Essa elenca e/o spiega i diritti e i doveri (molto spesso sconosciuti) che l'utente ha nei confronti del software.
Perchè non posso modificare il codice di un programma e renderlo disponibile a tutti se questo presenta dei difetti ed è possibile migliorarlo?
Questa è più o meno la domanda che Stallman si chiedeva quando l'industria dell'informatica iniziò a mettere gli occhi sui software. Fu allora che Stallman, nel 1985, rinunciando al suo lavoro, decise di iniziare il suo progetto GNU creando la licenza GPL. Più tardi, nel 1998, venne dato inizio al movimento open source (da Bruce Perens ed Eric Raymond). I principi di entrambi i movimenti sono stati già presentati, la lotta al software proprietario rivendica alcuni diritti negati agli utenti.
Il movimento open source, venendo dopo il progetto GNU avviato da Stallman, cercava e cerca tuttora di rimediare ad alcune questioni ancora irrisolte. La prima questione è stata già accennata e riguarda il doppio significato che la parola free assegna al software: libero o gratis? A tale proposito il movimento open source ha appunto suggerito un termine alternativo, ovvero quello di software open source.
La seconda questione coinvolge invece le licenze. Il software libero, così come definito dal progetto GNU di Stallman, viene lasciato con una licenza GNU GPL (GNU General Public License), oppure più semplicemente GPL. Stallman e Moglen scrissero questa licenza per distribuire i programmi appartenenti al progetto GNU. Nel 2007 è stata scritta la versione 3 della licenza.
Alle quattro libertà (di uso, di copia, di modifica e di distribuzione) definite dal software libero, nella licenza GPL si aggiunge un nuovo e importante vincolo: la licenza del prodotto software non va modificata. Di sicuro il pensiero di Stallman era rivolto alle case produttrici di software, che senza l'ultimo vincolo potevano allora appropriarsi del software e del lavoro di altre persone.
Esiste anche una versione meno restrittiva della GNU GPL, ovvero la GNU LGPL (GNU lesser General Public License) creata sempre dalla FSF per consentire l'uso di librerie. A differenza del GNU GPL la GNU LGPL non richiede che l'eventuale software usato dal programma sia rilasciato sotto la stessa licenza. Il movimento open source, invece, aggiorna un elenco delle licenze che rispondono ai requisiti e alla qualità prevista per il software open source. Le licenze GPL ed LGPL vengono riconosciute open source (altre licenze riconosciute sono quella BSD e MIT).
La particolarità delle licenze open source è che gli autori invece di vietare, permettono non solo di usare e copiare, ma anche di modificare, ampliare, elaborare, vendere e quant'altro. E tutto questo senza imporre obblighi per ricompensare economicamente gli autori [4].

Materiale consultato:
[1] Progetto GNU: http://www.gnu.org/philosophy/free-sw.it.html;
[2] Software freeware: http://it.wikipedia.org/wiki/Freeware;
[3] Movimento open source: http://www.opensource.org/;
[4] Licenze: http://it.wikipedia.org/wiki/Licenza open source;
[5] Breve storia del software libero e GNU Linux (il video qui sotto riportato)



Vi consiglio anche questo interessante documentario:


Non mi rimane che augurarvi una buona visione.

venerdì 18 giugno 2010

CSS, la formattazione del testo

La formattazione del testo attraverso i fogli di stile migliora di molto la resa finale del documento oltre a semplificare il compito per il web designer che adesso dispone di utili proprietà per: specificare un elenco di font da usare per il documento, usare dimensioni assolute o relative per i font, modificare il sistema di interlinea (la spaziatura fra le righe), applicare particolari decorazioni al testo etc... Andiamo per ordine e iniziamo subito la presentazione delle proprietà per la gestione del testo.

font-family
Una volta nell'HTML si indicava un solo font da usare per l'elemento del documento, e se questo non era disponibile presso l'utente? Il browser applicava (lo fa tutt'ora se scrivete il documento esclusivamente in HTML, senza usare CSS) un font di default. Ovviamente questo non garantisce la stessa impressione che il web-designer voleva trasmettere al lettore! Con la proprietà font-family dei fogli di stile è possibile impostare il tipo di carattere da assegnare al testo e da lasciare in eredità agli elementi figli. Le novità portate dai fogli di stile non si esauriscono alla possibilità di ereditarietà ma vanno ben oltre, con la proprietà font-family il web designer può specificare non uno ma bensì una lista di font!
E' il web designer che suggerisce al browser questo elenco, tutti i fonti sono quindi compatibili con lo stile grafico adottato nel documento (almeno così dovrebbe essere).
La lista raccoglie un elenco di font, ognuno separato dal successivo da una virgola. Attenzione, se il nome di un font è composto da più parole occorre racchiudere lo stesso fra virgolette! La lista di font deve poi terminare con un punto e virgola (per rendere valida la regola!). Ogni sistema operativo mappa dietro alcuni nomi di famiglie di caratteri uno o o più font predefiniti. Si consiglia di mettere al termine della lista una famiglia di font, come ultima possibilità! Le famiglie di font definite dal W3C per i fogli di stile sono: serif, sans-serif, cursive, fantasy e monospace. All'interno di queste famiglie di caratteri vengono quindi mappati tutti i font simili tra loro. La sintassi prevista per la scelta dei font deve rispettare la seguente struttura: selettore {font-family: font1,font2,...,famiglia_generica;}. Ecco subito un esempio: p {font-family: Arial, Helvetica, sans-serif;}.

font-size
Questa proprietà permette di regolare le dimensioni dei font, si applica a tutti gli elementi ed è ereditata dagli elementi figli. La dimensione di un font può essere assoluta (indipendente cioè da nessun'altra dimensione) oppure relativa (valutata in relazione alle dimensioni dell'elemento padre!). Alcune parole chiavi usate per le dimensioni assolute sono: xx-small, x-small, small, medium, large, x-large, xx-large, px (per i pixel), cm (per i centimetri), mm (per i millimetri), pt (per i punti, la più usata) e in (per i pollici). Le parole chiavi per i valori relativi sono: smaller, larger, em e % (per i valori percentuali). Un esempio: p {font-size: 12px;}.

font-weight
Esprime il peso del testo ovvero l'intensità e lo spessore dei punti che disegnano i caratteri. Si applica a tutti gli elementi e viene ereditato dagli elementi figli. La sintassi prevista dal W3C è la seguente: selettore {font-weight: valore;}. Dove valore può essere: un valore numerico che va da 100 a 900, normal (che corrisponde a 400), bold (che corrisponde a 700), bolder (più pesante rispetto al testo dell'elemento padre) e infine lighter (più leggero rispetto al testo dell'elemento padre). Un esempio: p {font-weight_ bold}

font-style
Assegna uno stile al testo, osserva questa sintassi: selettore {font-style: valore}. Questi i valori previsti: normal per il testo normale (valore di default), italic per il testo scritto in corsivo e oblique per schiacciare ancora di più il testo rispetto a quanto già fa italic. Un esempio: p {font-style: italic;}.

line-height
Descrive lo spazio che deve esistere fra due linee di testo. Osserva questa sintassi: selettore {line-height: valore;}. I possibili valori sono: normal, le righe di testo sono separate come solitamente avviene (è l'impostazione di default); numero, lo spazio fra le righe corrisponde al prodotto fra la dimensione data al font e il numero scelto; numero unità, lo spazio fra le righe di testo coincide con il valore e l'unità di misura data; numero%, lo spazio fra le righe di testo è una percentuale della dimensione data al font. Un esempio: p {line-height: 15px;}

font
Consente di specificare su unica riga tutte le (singole) proprietà fin qui viste. La sintassi da rispettare è la seguente: selettore {font: valori;}. Attenzione, i valori delle singole proprietà sono separati fra loro da un carattere di spazio. Per la lista di font, invece, occorre usare una o più virgole come elemento separatore.

Font di sistema
Vi piacerebbe usare nel documento gli stessi font usati dal sistema operativo?
Con i fogli di stile è possibile fare anche questo. A tale proposito il W3C ha definito le parole chiavi per far riferimento agli elementi del sistema operativo che prevedono all'interno il testo. Ecco l'elenco delle parole da ricordare: caption, per il font usato nei pulsanti; icon, per il font usato nelle label delle icone; menu, per il font usato nel menu dei programmi; message-box, per il font usato nei messaggi di sistema; status-bar, per il font usato dalla barra di stato. Un esempio: p {font: menu}.
Notate l'assenza di altri parametri, in questo modo non solo si userà il font di sistema ma verrà rispettato anche lo stile e le dimensioni date dal sistema operativo all'elemento di riferimento scelto!

Allineamento del testo
La sintassi prevista è la seguente: selettore {text-align: valore;}. Dove valore può essere: left, allinea il testo a sinistra; right, allinea il testo a destro; center, allinea il testo al centro; justify, giustifica il testo a destro e a sinistra. Un esempio: p {text-align: justify}.

text-decoration
Con questa proprietà possiamo assegnare al testo alcune semplici decorazioni. La sintassi da rispettare è la seguente: selettore {text-decoration: valore1, valore2, ...;}. I possibili valori sono: none, per nessuna decorazione; underline, il testo viene sottolineato; overline, il testo viene marcato in alto con una linea; line-through, il testo viene barrato da una linea; blink, il testo lampeggia! Un esempio: #urgent {text-decoration: blink;}.

giovedì 17 giugno 2010

CSS, gestione dello sfondo

Se prima di iniziare a usare i fogli di stile avete fatto in passato qualche esperienza con il codice dell'HTML sapete allora che colori e sfondi potevano essere assegnati alle tabelle e all'elemento body del documento. E che effetti! Le limitazioni dell'HTML erano combattute proprio con le tabelle. Spesse volte, ricordo, si costruiva la struttura del sito all'interno di tabelle con celle trasparenti e comunque riempite con immagini di contorno nel tentativo di centrare lo sfondo e allinearlo così come esso doveva apparire. Senza questi stratagemmi l'immagine di sfondo veniva ripetuta fino a riempire tutta la pagina!
I fogli di stile mettono fine a questo genere di lavori, adesso è possibile regolare lo sfondo attraverso le proprietà (singole): background-color, background-image, background-repeat, background-attachment e background-position. Se vogliamo invece descrivere le proprietà dello sfondo su un unica riga possiamo farlo attraverso la proprietà (multipla) background.

background-color
Attraverso questa proprietà possiamo assegnare all'elemento un colore di sfondo. La sintassi dettata dalle specifiche del W3C è la seguente: selettore{background-color: valore}, dove valore corrisponde a una delle strutture già viste per la selezione di un colore oppure corrisponde alla parola chiave trasparent.

background-image
Attraverso questa proprietà possiamo assegnare all'elemento un'immagine di sfondo. La sintassi dettata dalle specifiche del W3C è la seguente: selettore{background-image: url(valore);}, dove valore può corrispondere a none (nessuna immagine) oppure a un indirizzo (assoluto o relativo) che punta alla risorsa e quindi all'immagine.
Osservazione: conviene impostare solo il colore oppure solo l'immagine?
La logica (quella che stabilisce il comportamento del browser) dice che conviene impostare entrambe le proprietà, anche se l'immagine prevale sul colore scelto. Perché , allora, impostare entrambi i valori? Se il browser dell'utente ha disabilitato la visualizzazione delle immagini (oppure la stessa immagine non è più disponibile presso l'url indicato, ad esempio) l'oggetto verrà riempito con il colore scelto. Scegliete sempre un colore di sfondo per l'oggetto!

background-repeat
Attraverso questa proprietà possiamo suggerire al browser come ripetere l'immagine nell'oggetto. La sintassi dettata dalle specifiche del W3C è la seguente: selettore{background-repeat: valore;}, dove valore corrisponde a uno dei seguenti valori: repeat, l'immagine viene ripetuta fino a riempire tutto l'elemento (come fa di default l'HTML); repeat-x, l'immagine viene ripetuta fino a riempire in orizzontale tutto l'elemento; repeat-y, l'immagine viene ripetuta fino a riempire in verticale tutto l'elemento; no-repeat, l'immagine è riportata nell'oggetto una sola volta (a partire dall'angolo in alto a sinistra).

background-attachment
Attraverso questa proprietà possiamo assegnare all'immagine dell'elemento la modalità di fissaggio alla pagina. La sintassi dettata dalle specifiche del W3C è la seguente: selettore{background-attachment: valore;}, dove valore può corrispondere a: scroll (l'immagine scorre assieme al testo del documento) oppure a fixed (l'immagine resta attaccata al documento e il testo gli scorre sopra).

background-position
Attraverso questa proprietà possiamo indicare le coordinate da applicare all'immagine dell'elemento. La sintassi dettata dalle specifiche del W3C è la seguente: selettore{background-position: ascissa ordinata;}.

background
Attraverso questa proprietà possiamo assegnare, come dicevo all'inizio, tutte le singole proprietà fin qui viste. La sintassi prevede l'elenco dei valori (separati da un carattere di spazio) in un ordine anche diverso da quello che presento qui:
selettore{background-color background-image background-repeat background-attachment background-position;}
Notate la presenza del carattere ; che chiude la lista! Come dicevo poco fa l'ordine delle singole proprietà non è importante (è sufficiente la sola presenza della proprietà background-color per validare tutta la regola), tanto il browser riesce in ogni caso ad associare i valori alle singole proprietà dal momento che esse non danno luogo ad ambiguità e incomprensioni.