Tutorial Perl/Tk.

Iniciado por ^Tifa^, 19 Noviembre 2008, 21:34 PM

0 Miembros y 1 Visitante están viendo este tema.

^Tifa^

Ya que no he visto referencia alguna en la web sobre tutoriales de Perl/Tk en Espanol.
Aqui presento uno como parte de mi colaboracion personal......

Que necesita tu SO para ejercer esto?

1 - El interprete Perl.

Nada mas. No es requerido que tengas las librerias TK instaladas en tu SO, ya que
en este caso utilizare el modulo Perl::Tk el cual no es mas que una implementacion
de algunos 'widgets' de Tk, mas son independientes y no requieren ni trabajan directamente
con las librerias de Tk.

Si disponemos de Perl, tenemos que bajar el Modulo Perl::Tk de la web de Cpan. Para ello abrimos
una terminal Shell y hacemos con el usuario 'root' lo siguiente.

bash$ perl -MCPAN -e shell

Si es la primera vez que ejecutas la terminal de CPAN te aparecera un cuestionario de preguntas
de configuracion.. deberas responder segun tus gustos. Al terminar entramos al interprete de cpan.

cpan>

Cuando lo veas sencillamente manda a buscar he instalar el modulo requerido.

cpan> install Tk

Cpan se encargara de buscar, bajar he instalar todo. al finalizar puedes salir de alli, y abrir un editor
para comenzar a trabajar con perl y Tk.

En el editor colocamos lo siguiente :

#!/usr/bin/perl
use strict;
use warnings;
use Tk;

Expongo.. En la primera linea '#!/usr/bin/perl' indica cual sera el interprete que llamara la aplicacion.
La segunda y tercera linea 'use strict' y 'use warnings' son 2 pragmas de Perl, estas sirven la primera para
recordarnos a codear explicitamente en un lenguaje estructurado limpio (nada de break, continue, goto, etc).
Y la segunda sirve como Debugger en caso de que queramos depurar al ejecutar el script.

La tercera linea 'use Tk' sencillamente importa el modulo 'Tk' a nuestra aplicacion.

#!/usr/bin/perl
use strict;
use warnings;
use Tk;

my $ventana = MainWindow->new();
$ventana->minsize(qw(400 400));
$ventana->resizable('FALSE','FALSE');
$ventana->Label(-text => "Hola Mundo")->pack();

MainLoop();

Guardamos todo lo anterior y ejecutamos :

bash$ perl aplicacion.pl

Se abrira una ventana con un Hola Mundo.

Explicaciones ::

my $ventana = MainWindow->new();
* En esta linea declaramos una variable 'my $ventana' que inicializa un objeto que funcionara como la ventana principal.
Perl tiene 3 tipos de declaracion para las variables, las escalares siempre comienzan con simbolo de dolar $ y guardan cualquier dato caracter o numerico, los arreglos que siempre comienzan con el simbolo arroba @ y por igual guardan cualquier dato caracter o numerico y las variables hash que comienzan con el simbolo % y son variables que hacen referencia a un caracter o numero .. En resumen en Perl no hay que declarar el tipo de dato a guardar dentro de una variable. (Para mas info de tipos de variables, averiguen sobre programacion en Perl).

$ventana->minsize(qw(400 400));
* En esta linea se especifica que el tamano minimo de nuestra ventana sera 400 de ancho y 400 de largo.

$ventana->resizable('FALSE','FALSE');
* EN esta linea se especifica que la ventana no podra ser reducida ni agrandada tanto por ancho como por largo.

$ventana->Label(-text => "Hola Mundo", -font => 'Courier')->pack();
* En esta linea creamos un objeto widget Label que llevara como Texto la palabra 'Hola Mundo'. Todos los objetos de Tk tienen tienen
opciones en este caso el objeto Label le estamos pasando una opcion de Texto a presentar en la ventana, en este caso 'Hola Mundo',
al objeto Label tambien le pasamos otra opcion, -font es el tipo de fuente que llevara definido nuestro 'Hola Mundo' en este caso
utilizo Courier pero igual pueden utilizar otro soportado dentro de su SO. las opciones de los objetos widgets deben ir separadas por coma.

Luego tenemos pack(), este lo que hace es encapsular o guardar el objeto Label dentro de ventana que es nuestro objeto principal. Es obligatorio encapsular el objeto dentro de la ventana padre. En caso de que obvies encapsularla.. perl no sabra donde debe guardar a Label por ende no se presentara en pantalla cuando ejecutemos el script.. ya que lo que saldra en pantalla es el objeto padre ventana y si ventana no tiene un hijo encapsulado no lo mostrara.

pack() aparte de encapsular funciona como un manejador de tamano igual que su contraparte grid().. los cuales explicare mas adelante en otro tutorial.

* MainLoop()
- En esta ultima linea creamos un Loop del objeto principal.. cual es el objetivo de esto? el objetivo es que la linea anterior se encarga de llamar y responder a todos los eventos pasados al objeto principal ventana. Si obviamos esta ultima linea nuestro objeto principal jamas se desplegara por pantalla. Ya que MainLoop maneja todos los eventos del objeto padre.


#!/usr/bin/perl
use strict;
use warnings;
use Tk;

my $ventana = MainWindow->new();
$ventana->minsize(qw(400 400));
$ventana->resizable('FALSE','FALSE');
$ventana->Label(-text => "Hola Mundo")->pack();
my $texto = $ventana->Text(-width => 20, -height => 15, -background => 'white')->pack();
my $entrada = $ventana->Entry(-width => 20, -background => 'white')->pack();
$ventana->Button(-text => "Copiar & Pegar", -command => \&copia)->pack();

MainLoop();

sub copia
{
my $resultado = $entrada->get();
$texto->insert("end", "$resultado");
}

Comentarios :

my $texto = $ventana->Text(-width => 20, -height => 15, -background => 'white')->pack();
* Aca creamos una variable escalar, que guarda un objeto widget de tipo Texto, Texto en este caso tiene 3 opciones
que es de tamano largo y ancho y su color de fondo. Utilizamos pack() al final para especificar que el objeto Text
sera encapsulado dentro del objeto padre ventana.

my $entrada = $ventana->Entry(-width => 20, -background => 'white')->pack();
* Aca creo otra variable que guarda un objeto widget de tipo Entrada, nuevamente con 2 opciones pasadas
siempre separadas por comas, las opciones indican el color de fondo y el largo que llevara el widget.

$ventana->Button(-text => "Copiar & Pegar", -command => \&copia)->pack();
* Aqui declaro un objeto widget tipo Boton, con 2 opciones una el texto a representar el boton, y la otra el
evento que realizara el boton al ser clickeado. Al ser clickeado el boton, este llamara a la funcion 'copia'

sub copia
{
my $resultado = $entrada->get();
$texto->insert("end", "$resultado");
}
* Esta es la funcion llamada cuando el boton es clickeado. Dentro de la funcion se declara una variable escalar '$resultado'
que guardara los datos insertados dentro de la variable '$entrada', recuerden que la variable '$entrada' guarda un objeto Entry cualquier info digitada aqui sera captada get() y guardada en la variable '$resultado'.

$texto->insert("end", "$resultado");
* '$texto' es la variable que guarda al objeto widget de Texto, al llamar a 'insert' este lo que le indica que insertara cierta informacion dentro del widget, en este caso se insertara la variable '$resultado'.

leogtz

Excelente ^TiFa^, mi primera ventana en PERL, esto me servira mucho, me ha animado mas en la programacion en Perl.

Sigue asi  :D

Saludos.
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

carlitos.java

se ve bueno, lo leeré y comento más.

AxXioma

Excelentísimo ^TiFa^ cuando quieras haces mas tutoriales. Ya sabes como me vienen.

GRAAAAAACIASSSSSSSSSSSSSSSS. ;D




.::Cuanto mas conocimiento adquieres, más te das cuenta del que hay a tu alrededor::.

^Tifa^

Bueno, Seguimos dandole continuacion adonde me he quedado :P

Vamos a conocer mas objetos 'widgets' de Tk dentro de Perl :)

Utilizo el ejemplo anteriormente ya dado  :


#!/usr/bin/perl
use strict;
use warnings;
use Tk;

my $ventana = MainWindow->new();
$ventana->minsize(qw(400 400));
$ventana->resizable('FALSE','FALSE');
$ventana->Label(-text => "Hola Mundo")->pack();
my $texto = $ventana->Text(-width => 20, -height => 15, -background => 'white')->pack();
my $entrada = $ventana->Entry(-width => 20, -background => 'white')->pack();
$ventana->Button(-text => "Copiar & Pegar", -command => \&copia)->pack();
$ventana->Button(-text => "Limpiar", -command => \&limpieza)->pack();


MainLoop();

sub copia
{
my $resultado = $entrada->get();
$texto->insert("end", "$resultado");
}

sub limpieza
{
$entrada->delete('0',"end");
$texto->delete('0.0', "end");
}

Aqui agregue otro boton nuevo y otra funcion.

* $ventana->Button(-text => "Limpiar", -command => \&limpieza)->pack();
Este es el boton nuevo, que llama a la funcion limpieza.

*sub limpieza
{
$entrada->delete('0',"end");
$texto->delete('0.0', "end");
}
- Aqui tenemos 2 lineas interesantes, llamamos a las variables ya declaradas $entrada y $texto y le pasamos una funcion de configuracion 'delete' dicha funcion de Tk soporta 2 parametros que son "end" que es hasta donde existan caracteres, y '0' quiere decir 1 linea, mas '0.0' hace referencia a varias. Recordemos que la variable $texto guarda un widget tipo Texto que ocupan varias filas y columnas, mas la variable $entrada solo ocupa 1 linea. :)

Ahora que ocurre si queremos poner en nuestra ventana principal que los botoncitos aparezcan alineados de forma horizontal o vertical exacta?? Creamos una ventana nueva :)

#!/usr/bin/perl
use strict;
use warnings;
use Tk;

my $ventana = MainWindow->new();
$ventana->minsize(qw(250 200));
$ventana->maxsize(qw(250 200));
$ventana->Button(-text => "Pinchame", -width => 10, -relief => 'groove')->grid(-row => 1, -column => 1, -padx => 2);
$ventana->Button(-text => "Clickeame", -width => 10, -relief => 'sunken')->grid(-row => 1, -column => 2, -padx => 2);
$ventana->Button(-text => "Soy un Boton", -width => 10, -relief => 'raised')->grid(-row => 2, -column => 1, -pady => 2);
$ventana->Button(-text => "Pick Me", -width => 10, -relief => 'flat')->grid(-row => 2, -column => 2, -pady => 2);

MainLoop();

* $ventana->maxsize(qw(250 200));
Esta opcion de configuracion a nuestro objeto principal, especifica cual es el tamano maximo de largo y ancho que nuestra ventana soportara.. dependiendo el valor que indiquemos el usuario podra agrandar y disminuir la ventana agarrandola con el raton por los bordes. En caso que a la ventana le digamos que el tamano minimo y maximo son iguales, nadie podra agrandar o disminuir la ventana, (igual manera ocurre si hacemos $ventana->resizable('FALSE','FALSE')) En caso que indiquemos valores distintos podremos disminuir o agrandar la ventana hasta el tamano maximo y minimo indicado.

* $ventana->Button(-text => "Pinchame", -width => 10, -relief => 'groove')->grid(-row => 1, -column => 1, -padx => 2);
Volvemos con los botones, aqui utilizamos mas opciones disponibles al objeto Button aparte de la opcion text, le indico el tamano de largo (width) y el estilo (relief) que tendra el boton. Tk posee varios estilos que podemos aplicar a nuestros objetos 'widgets' entre estos tenemos (groove, flat, sunken, raised). Tambien podemos pasarle colores de fondo y de letra a los botones, basta con utilizar dentro de las opciones.. para colorear el fondo -background => 'color' y para las fuentes -foreground => 'color'.
Por Ejemplo :

$ventana->Button(-text => "Pinchame", -width => 10, -relief => 'groove', -background => 'black', -foreground => 'yellow')

Pero vemos que ya no uso pack() para encapsular los botones dentro del objeto padre ventana sino grid()??? que es grid()???
Tanto pack y grid, son 2 paquetes de geometria especificos de Tk. Ambos tienen opciones que podemos pasarle distintas, los dos encapsulan el objeto 'widget' dentro del objeto padre principal..

Entonces para que necesito grid si pack hace lo mismo o inversa?
Por las opciones que grid ofrece que pack no :) grid nos permite alinear exactamente nuestro widget hijo en fila - columna (Con pack no podemos hacer esto ;) ). Fijense que en grid utilizo 2 opciones llamada row y column (que es fila y columna) Asi puedo ir moldeando cada boton en este caso ordenadamente en la columna 1 fila 1, en la columna 1 fila 2, en la columna 2 fila 1, y asi sucesivamente :)

Ahi otra opcion que le estoy pasando a grid() se llama padx y pady, que hacen estas dos?
padx indica la cantidad de espacio a otorgar al widget para separarlo horizontalmente del otro widget.
pady indica la cantidad de espacio a otorgar al widget para separarlo verticalmente del otro widget.

Para probar pueden quitar a los botones las opciones padx y pady y ejecutar la aplicacion.. que ocurre?? Que salen los 4 botones pegados. Mas si aplican padx con una numeracion de espacio elegida por ustedes, podran ver como los botones se van espaciando horizontalmente.. y si le agregan pady con una enumeracion de espacio elegida por ustedes, podran ver como los botones se van separando entre ellos verticalmente...

padx y pady aplican en pack() tambien :)

No confundir padx y pady con ipadx y ipady, estos 2 ultimos ejercen la misma funciones que los 2 primeros solo que dentro del widget hijo (Boton en este caso) y no fuera de ellos. O sea dependiendo de la enumeraciones que pasemos a ipadx y ipady se aplicaran pero a modificar el tamano (ancho y largo) del boton en este caso.


my $ventana = MainWindow->new();
$ventana->minsize(qw(250 200));
$ventana->maxsize(qw(250 200));
my $frama = $ventana->Frame->pack();
$frama->Checkbutton(-text => "Pinchame", -borderwidth => 3, -relief => 'groove')->pack(-pady => 10);
$frama->Radiobutton(-text => "Clickeame", -borderwidth => 3, -relief => 'groove')->pack();
$frama->Label(-text => 'Soy una palabra')->pack();

Perl::Tk, Tambien soporta Frames :) como muchos saben dentro de los Frames podemos encapsular varios hijitos 'widgets' en este caso encapsulo 2 un Checkbutton y un Radiobutton, estos ultimos 2 igual que los botones normales, acceptan como opcion la llamada a una funcion 'command' por ejemplo :

* $frama->Checkbutton(-text => "Pinchame", -borderwidth => 3, -relief => 'groove', -command => \&copia)->pack(-pady => 10);

Asi cada vez que el usuario clickee se llamara a la funcion copia.

my $ventana = MainWindow->new();
$ventana->minsize(qw(250 200));
$ventana->maxsize(qw(250 200));
$ventana->Scrolled('Text', -background => 'white')->pack(-fill => 'both', -expand => 'true');

* $ventana->Scrolled('Text', -background => 'white')->pack(-fill => 'both', -expand => 'true');
Aqui declaramos un objeto widget del tipo Text - texto. Con la unica variante que le agregamos una barra scroll, las barras scrolls nos sirven por si abrimos un documento un poco extenso poder leerlo hasta el final. Facilidad de las cuales carecemos sino usamos barra scrolls como el primer ejemplo hacia el widget Texto por Ejemplo ::

* $ventana->Text(-width => 20, -height => 10, -background => 'white')->pack();

Tanto al widget Texto con Barra Scroll como sin esta, le podemos indicar el tamano (ancho*alto) deseado o podemos cubrir la ventana completa pasandole ciertas opciones a pack por ejemplo -fill y -expand. Estas 2 particulares opciones hacen lo siguiente, la primera 'fill' indica que ese widget ocupara el mismo tamano total verticalmente que posee la ventana principal, siempre se lo indiquemos asi a fill con la opcion 'both' que quiere decir de lado a lado en el idioma Tk.  y la opcion -expand = a verdadero indica que dicho widget hijo no solo ocupara verticalmente el tamano de la ventana sino que tambien ocupara horizontalmente el tamano total de esta...

Aqui posteo un ejemplo de un archivo un poco extenso abierto dentro del widget Texto con Barra Scroll.


#!/usr/bin/perl
use strict;
use warnings;
use Tk;


my $ventana = MainWindow->new();
$ventana->minsize(qw(250 200));
$ventana->maxsize(qw(250 200));
my $entrada = $ventana->Scrolled('Text', -background => 'white')->pack(-fill => 'both', -expand => 'true');

open(AA,"/etc/profile");
my @todo = <AA>;
$entrada->insert("end", "@todo ");
close (AA);

MainLoop();

(Nota :: Solo funciona en Linux la ubicacion '/etc/profile' Si estas en otra plataforma, indicar otro directorio
y su respetivo archivo de texto :) )

^Tifa^

En el siguiente ejemplo, se trabaja con Perl, Tk y el modulo DBI para conectarse a una DB de Mysql activa local. Si la conexión es satisfactoria entonces te sale otra ventanita pidiendote que ingreses la consulta SQL a realizar dentro de mysql, luego de obtener los datos estos son imprimidos en una pantalla de la ventana Tk en cuestion.

:) Para los que tienen dudas de como mezclar Perl/Tk con otros modulos por ejemplo DBI para Mysql.

Código (perl) [Seleccionar]


#!/usr/bin/perl
use strict;
use warnings;
use Tk;
use DBI;

my $ventana = MainWindow->new();
$ventana->minsize(qw(400 400));
$ventana->maxsize(qw(400 400));

my $menu = $ventana->Menu(-relief => 'flat');
$ventana->configure( -title => "Proyecto I", -menu => $menu);

my $comando = $menu->Menubutton( -label => "Archivo", -underline => 1);
$comando->command( -label => "Salir", -command => sub { exit(1); } );

my $comando1 = $menu->Menubutton( -label => "Opciones" );
$comando1->command( -label => "Salida", -command => sub { exit(1); } );


my $frama = $ventana->Frame(-borderwidth => 2, -relief => 'groove')->pack();
$frama->Label(-text => "Base de Datos" )->pack();
my $a = $frama->Entry(-width => 20, -background => 'white')->pack(-padx => 10);
$frama->Label(-text => "Usuario" )->pack();
my $b = $frama->Entry(-width => 20, -background => 'white')->pack(-padx => 10);
$frama->Label(-text => "Contrasena" )->pack();
my $c = $frama->Entry(-width => 20, -background => 'white', -show => '*')->pack(-padx => 10, -pady => 10);

my $boton = $ventana->Button(-text => "Conectar", -relief => 'raised', -width => 15, -command => \&conectar )->pack(-pady => 10);

#$ventana->Photo('imagen', -file => 'mysql.gif');
#$ventana->Label(-image => 'imagen', -relief => 'groove')->pack(-pady => 10);


MainLoop();


sub conexión {

my $servidor = $a->get();
my $usuario = $b->get();
my $contrasena = $c->get();

my $conexión = DBI->connect("dbi:mysql:$servidor", $usuario, $contrasena, { PrintError => 0 } );

}


sub conectar {

do conexión;

if ( conexión ) {
my $dialogo = $ventana->messageBox(-message => "Conectado Satisfactoriamente!", -icon => 'warning', -type => 'Ok');
$boton->configure( -state => 'disabled' );

& consulta();

} else {

my $dialogo = $ventana->messageBox(-message => "Error de conexión!!", -icon => 'error', -type => 'Ok');

}
}


sub consulta {

my $ventanita = MainWindow->new();
$ventanita->Label(-text => "Escribe la Consulta")->pack(-padx => 10);
my $consult = $ventanita->Entry(-width => 30, -background => 'white', -foreground => 'red')->pack(-padx => 10);

$ventanita->Button(-text => "Realizar", -width => 20, -relief => 'sunken', -command => sub {

my $consulta1 = $consult->get();

do conexión;
my $peticion = conexión->prepare( qq{$consulta1} ) or my $dialogo = $ventanita->messageBox(-messagebox => "Consulta mal formulada!!", -icon => 'error', -type => 'Ok');

$peticion->execute();

my $texto = $ventanita->Text( -width => 40, -height => 30, -background => 'white' )->pack();

while (my @todo = $peticion->fetchrow_array) {

$texto->insert("end", "@todo  ");
$texto->insert("end", "\n");

}

$peticion->finish();

})->pack();
}


Seth_

¡Justo lo qeu buscaba! Pero dónde encuentro un manual completamente en castellano sobre esto? :rolleyes:

Banti

Ugh.. A este es el legendario jerogrifico...
Mejor termino de ver el tuto de erik y luego sigo con este.

k-k0

yo le estuve dando un tiempo a perl/tk y ahora estoy usando perl/gtk y la verdad se nota la potencia :) pero siempre manteniendo simplicidad...
Hacking is an art, don't screw it ...

^Tifa^

No es un Jeroglifico .... es solo un poco.... manual.  :P es todo.

No avanze mas este tutorial porque desconozco quienes estan sumamente interesados, pero podia crear como demostracion una simple aplicacion utilizando Perl/Tk y el modulo DBI para trabajar con una aplicacion grafica que haga cosillas a una DB relacional tipo Mysql u Oracle o Postgresql...

Me gustaria ver algun tutorial de Perl/QT pero no he encontrado ni en ingles ni en espanol nisiquiera he encontrado el modulo QT en Cpan para Perl  :-\

Hasta la fecha no he visto tutoriales Perl/Tk en castellano.