Barra laterale

programmazione:perl:perl_dbi_gtk

Creazione di programmi con Perl, DBI, GTK

Autore: Fabio Di Matteo
Ultima revisione: 03/02/2015 - 15:15

In questo articolo vedremo come creare applicazioni Perl (script) che fanno uso di interfacce grafiche e di accesso a basi di dati. Espanderemo il codice dell'articolo Introduzione alla librerie Gtk2 con Perl con le funzionalita di DBI, il layer piu' usato per diverse tipologie di basi dati di Perl.

Il codice

Fonti per quanto riguarda la parte DBI :http://zetcode.com

db.pl

#!/usr/bin/perl
 
 
use Glib qw/TRUE FALSE/;
use Gtk2 '-init';
use Gtk2::SimpleList; 
use DBI;
 
#Questa funzione è da usare solo su sqlite2. 
#Sqlite3 supporta le query "... IF NOT EXIST..."
sub tableExist
{
	#Connessione al database
	my $dbh = DBI->connect(          
		"dbi:SQLite2:dbname=$_[0]", 
		"",                          
		"",                          
		{ RaiseError => 1 },         
	) or die $DBI::errstr;
 
	#Conta le tabelle con nome $_[1] 
	my $sth = $dbh->prepare("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='$_[1]';");
	$sth->execute();
 
	#Mette il risultato della conta nell'array @row. Ovviamente prenderemo
	#in considerazione solo @row[0] ;
	my $row;
	@row = $sth->fetchrow_array();
 
	#Se @row[0] è uguale a 1 la tabella esiste, altrimenti no.
	if (@row[0]=='1'){ return TRUE } else{ return FALSE} ;
 
}
 
 
sub createTable
{
	#Se la tabella esiste non la crea
	if (tableExist("test.db","persone")) { return ;}
 
 
	#Connessione al database
	my $dbh = DBI->connect(          
		"dbi:SQLite2:dbname=test.db", 
		"",                          
		"",                          
		{ RaiseError => 1 },         
	) or die $DBI::errstr;
 
	#Creo la tabella
	$dbh->do('CREATE TABLE "persone" (
						  "id" INTEGER NOT NULL ,
						  "nome" varchar(1) ,
						  "cognome" varchar(256) ,
						  "email" varchar(256) ,
						  PRIMARY KEY ("id") 
						);');
 
	#Disconnessione
	$dbh->disconnect();
 
 
}
 
 
sub updateGrid
{
	#Cancella tutti glielementi  della griglia
	splice @{$slist->{data}} ;
 
 
	#Connessione al database
	my $dbh = DBI->connect(          
		"dbi:SQLite2:dbname=test.db", 
		"",                          
		"",                          
		{ RaiseError => 1 },         
	) or die $DBI::errstr;
 
 
 
	my $sth = $dbh->prepare("SELECT * FROM persone;");
	$sth->execute();
 
	my $row;
	while ($row = $sth->fetchrow_hashref()) 
	{
		#Prelevo i dati dalla query nella seguente forma $row->{NOMECAMPO}
 
		#Aggiungo una riga al widget SimpleList (tratto $slist come un normalisimo array)
		push @{$slist->{data}}, [ $row->{id}, $row->{nome},$row->{cognome}, $row->{email}];
	}
	$sth->finish();
	$dbh->disconnect();
 
}
 
 
#Le callbacks dei bottoni
sub exit
{
	my ($widget, $window) = @_;
	$window->destroy;
 
}
 
sub delete_event
{
	$window->destroy;
	return TRUE;
}
 
 
sub add
{
	my ($widget, $window) = @_;
 
	#Connessione al database
	my $dbh = DBI->connect(          
		"dbi:SQLite2:dbname=test.db", 
		"",                          
		"",                          
		{ RaiseError => 1 },         
	) or die $DBI::errstr;
 
	#Inserisco qualche dato
	$nome=$txtNome->get_text();
	$cognome=$txtCognome->get_text();
	$email=$txtEmail->get_text();
	$dbh->do("INSERT INTO persone VALUES(null,'$nome','$cognome','$email')");
 
	#Disconnessione
	$dbh->disconnect();
	clearText();
	updateGrid();
}
 
sub del
{
	#Prende il valore delle cella nascosta contenente l'id
	@sel = $slist->get_selected_indices;
	$id=$slist->{data}[@sel[0]][0];
 
	#Connessione al database
	my $dbh = DBI->connect(          
		"dbi:SQLite2:dbname=test.db", 
		"",                          
		"",                          
		{ RaiseError => 1 },         
	) or die $DBI::errstr;
 
	$dbh->do("DELETE from persone where id=$id ;");
 
	#Disconnessione
	$dbh->disconnect();
	clearText();
	updateGrid();
 
 
	clearText();#svuota le entry
}
 
sub get
{
	#Prende l'indice selezionato e visualizza i dati nelle entry
	@sel = $slist->get_selected_indices;
 
	#Il metodo "$slist->get_selected_indices" prende un array di righe (@sel)
	#selezionate. Noi andremo a prendere solo una di queste righe in quanto
	#la selezione è singola nel nostro caso.
 
	#Riga selezionata
	$txtId->set_text($slist->{data}[@sel[0]][0]);
	$txtNome->set_text($slist->{data}[@sel[0]][1]);
	$txtCognome->set_text($slist->{data}[@sel[0]][2]);
	$txtEmail->set_text($slist->{data}[@sel[0]][3]);
 
}
 
sub save
{
	#Prende il valore delle cella nascosta contenente l'id
	@sel = $slist->get_selected_indices;
	$id=$slist->{data}[@sel[0]][0];
 
	#Connessione al database
	my $dbh = DBI->connect(          
		"dbi:SQLite2:dbname=test.db", 
		"",                          
		"",                          
		{ RaiseError => 1 },         
	) or die $DBI::errstr;
 
	#Prendo i valori delle entry
	$nome=$txtNome->get_text();
	$cognome=$txtCognome->get_text();
	$email=$txtEmail->get_text();
 
 
	$sql="UPDATE  persone SET  	nome =  '$nome', cognome =  '$cognome',	email =  '$email' 	WHERE  id =$id ;";
 
	$dbh->do($sql);
 
	#Disconnessione
	$dbh->disconnect();
	clearText();
	updateGrid();
}
 
sub clearText
{
	#Questa funzione cancella soltanto il contenuto delle entry
	$txtId->set_text('');
	$txtNome->set_text('');
	$txtCognome->set_text('');
	$txtEmail->set_text('');
 
}
 
 
#Crea la tabella se non esiste
createTable();
 
 
 
 
# crea la finestra principale e la collega ad alcune callback
$window = Gtk2::Window->new('toplevel');
$window->signal_connect(delete_event => \&delete_event);
$window->signal_connect(destroy => sub { Gtk2->main_quit; });#alla chiusura quit
 
 
# Alcune prprietà della finestra
$window->set_border_width(10);
$window->set_size_request(640, 600);
$window->set_title("Rubrica");
$window->set_position('center');
 
 
#Entry e label per l'inserimento e modifica
$txtId = Gtk2::Entry->new();
$txtId->set_editable (FALSE);
$txtNome = Gtk2::Entry->new();
$txtCognome = Gtk2::Entry->new();
$txtEmail = Gtk2::Entry->new();
$lblId = Gtk2::Label->new ("ID:");
$lblNome = Gtk2::Label->new ("Nome:");  
$lblCognome = Gtk2::Label->new ("Cognome:");
$lblEmail = Gtk2::Label->new ("Email:");
 
#Bottoni per le azioni
$btnDel = Gtk2::Button->new("Elimina");
$btnExit = Gtk2::Button->new("Esci");
$btnAdd = Gtk2::Button->new("Aggiungi");
$btnSave = Gtk2::Button->new("Salva");
#Callbacks bottoni
$btnExit->signal_connect(clicked => \&exit, $window);
$btnAdd->signal_connect(clicked => \&add, $window);
$btnDel->signal_connect(clicked => \&del, $window);
$btnSave->signal_connect(clicked => \&save, $window);
 
 
#Colonne della griglia e relativo tipo
$slist = Gtk2::SimpleList->new (
                'ID'    => 'text',
                'Nome'    => 'text',
                'Cognome'  => 'text',
                'email'     => 'text',
              );
 
#Nascondo alla vista la colonna ID
$idColumn = $slist->get_column (0);
$idColumn->set_visible(FALSE);
 
 
#Aggiorno la griglia con i contnuti del db
updateGrid();
 
#Dimensioni della griglia
$slist->set_size_request(400,400);
 
 
#Al doppioclick su una riga esegui la funzione "get"
$slist->signal_connect(row_activated => \&get, $window); 
 
 
 
 
 
$hbox0 = Gtk2::HBox->new(); 		#contenitore dell'intera area
$vbox0 = Gtk2::VBox->new(); 		#contenitore griglia e bottoni
$vbox1 = Gtk2::VBox->new();			#contenitore caselle di testo ed etichette
 
 
#Aggiungo ad hbox0 gli altri contenitore vbox0 e vbox1
$hbox0->pack_start($vbox0, TRUE, FALSE, 0);
$hbox0->pack_start($vbox1, TRUE, FALSE, 0);
 
#Aggiungo al cntenitore vbox1 i vari campi testo con le relative etichette
$vbox1->pack_start($lblId, FALSE, TRUE, 0);
$vbox1->pack_start($txtId, FALSE, TRUE, 0);
 
 
$vbox1->pack_start($lblNome, FALSE, TRUE, 0);
$vbox1->pack_start($txtNome, FALSE, TRUE, 0);
 
$vbox1->pack_start($lblCognome, FALSE, FALSE, 0);
$vbox1->pack_start($txtCognome, FALSE, FALSE, 0);
 
$vbox1->pack_start($lblEmail, FALSE, FALSE, 0);
$vbox1->pack_start($txtEmail, FALSE, FALSE, 0);
 
 
#Aggiungo al contenitore vbox0 la griglia e i bottoni sotto di essa
$vbox0->pack_start($slist, TRUE, FALSE, 0);
$vbox0->pack_start($btnAdd, TRUE, FALSE, 0);
$vbox0->pack_start($btnSave, TRUE, FALSE, 0);
$vbox0->pack_start($btnDel, TRUE, FALSE, 0);
$vbox0->pack_start($btnExit, TRUE, FALSE, 0);
 
 
 
# Aggiungo box0 a $window
$window->add($hbox0);
 
 
 
# mostra tutto
$window->show_all;
 
#Ciclo principale delle Gtk
Gtk2->main;
 
0;

Installazione delle dipendenze su Windows

Per prima cosa installare strawberryperl Perl e le runtime GTK (http://downloads.sourceforge.net/gladewin32/gtk-2.8.20-win32-1.exe) poi impartire i seguenti comandi dal terminale di windows(cmd):

Installazione delle Gtk2 per Perl

ppm install Glib
ppm install Cairo
ppm install Pango
ppm install Gtk2

Installazione DBI per sqlite2

perl -MCPAN -e shell
cpan> install DBI
cpan[2]> install DBD::SQLite2

Caricare il tema grafico delle GTK per Windows

Purtroppo per utilizzare il tema grafico per windows sembra che bisogna fare alcuni interventi manuali. Prima di tutto scaricare il bundle con le Gtk2, 32 o 64bit a seconda della versione installata di Strawberry Perl.

Dopodicchè entriamo nella cartella del bundle gtk e copiamo le cartelle “bin” ,“lib”, “etc” e “share” nella sottocartella di Strawberry [inst. di Strawberry]\perl\site\lib\auto\Gtk2 . Fatto questo possiamo caricare il tema nel nostro codice per con:

#Per caricare il tema grafico solo su windows.
if ($^O=='MSWin32') {Gtk2::Rc->set_default_files ("gtkrc")};

Il file “gtkrc” lo possiamo mettere dove vogliamo e deve contenere il seguente testo:

gtk-theme-name = "MS-Windows"  

programmazione/perl/perl_dbi_gtk.txt · Ultima modifica: 18/04/2018 - 15:49 (modifica esterna)