[Kde-devel-es] Tutorial: p3
Antonio Larrosa Jiménez
kde-devel-es@mail.kde.org
Tue, 1 Oct 2002 13:12:10 +0200
--Boundary-00=_KMYm9C6abutJx2c
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline
Hola,
Con un poco de retraso, aqu=ED llega la tercera parte del tutorial. En este=
=20
punto ya vamos a a=F1adir una barra de men=FA y un widget de texto rico o=20
texto con formato (rich text).
Pero bueno, lo mejor es leerlo.
Si teneis alguna duda, s=F3lo teneis que contestar al mensaje.
Saludos,
=2D-
Antonio Larrosa Jimenez
KDE core developer - larrosa@kde.org
http://devel-home.kde.org/~larrosa/
With a rubber duck,one's never alone --The Hitchhiker's Guide to the Galaxy
--Boundary-00=_KMYm9C6abutJx2c
Content-Type: text/html;
charset="us-ascii";
name="p3.html"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="p3.html"
<HTML>
<HEAD>
<TITLE>
Tutorial de KDE- p3
</TITLE>
</HEAD>
<BODY BGCOLOR=3Dwhite COLOR=3Dblack>
<H2><CENTER>p3</CENTER></H2> =20
<P ALIGN=3D"RIGHT">
<A HREF=3D"p4.html">Siguiente</A>
<A HREF=3D"p2.html">Anterior</A>
<A HREF=3D"index.html">Tabla de Contenidos</A></P>
Ya hemos creado una aplicación simple de KDE en p2, pero en la mayor=
ía de
los casos habr=E1 que usar un interfaz mas complicado que un simple bot&oac=
ute;n :-),
asi que veamos como añadir un widget principal standard con una barr=
a de men=FA.
<P>
<HR>
<BLOCKQUOTE><PRE>
#include <kapp.h>
#include "p3.h"
=20
int main( int argc, char **argv )
{
KApplication a( argc, argv, "p3");
=20
MainWindow *window=3Dnew MainWindow( "Tutorial - p3" );
window->resize( 400, 300 );
=20
a.setMainWidget( window );
window->show();
=20
return a.exec();
}=20
</PRE></BLOCKQUOTE>
<HR>
<DIV ALIGN=3DRIGHT>main.cpp</DIV>
<P>
<HR>
<BLOCKQUOTE><PRE>
#include <kmainwindow.h>
=20
class MainWindow : public KMainWindow
{
Q_OBJECT
public:
=20
MainWindow ( const char * name );
=20
public slots:
void fileOpen();
void fileSave();
};
</PRE></BLOCKQUOTE>
<HR>
<DIV ALIGN=3DRIGHT>p3.h</DIV>
<P>
<HR>
<BLOCKQUOTE><PRE>
#include "p3.h"
#include <kfiledialog.h>
#include <kapp.h>
#include <kmenubar.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kpopupmenu.h>
#include <qtextview.h>
=20
MainWindow::MainWindow ( const char * name ) : KMainWindow ( 0L, name )
{
setCaption("KDE Tutorial - p3");
QPopupMenu *filemenu =3D new QPopupMenu;
filemenu->insertItem( i18n( "&Open" ), this, SLOT(fileOpen()) );
filemenu->insertItem( i18n( "&Save" ), this, SLOT(fileSave()) );
filemenu->insertItem( i18n( "&Quit" ), kapp, SLOT(quit()) );
QString about =3D
i18n("p3 1.0\n\n"
"(C) 1999-2002 Antonio Larrosa Jimenez\n"
"larrosa@kde.org\t\tantlarr@supercable.es\n"
"Malaga (Spain)\n\n"
"Simple KDE Tutorial\n"
"This tutorial comes with ABSOLUTELY NO WARRANTY\n"
"This is free software, and you are welcome to redistribut=
e it\n"
"under certain conditions\n");
=20
QPopupMenu *helpmenu =3D helpMenu( about );
KMenuBar *menu =3D menuBar();
menu->insertItem( i18n( "&File" ), filemenu );
menu->insertSeparator();
menu->insertItem( i18n( "&Help" ), helpmenu );
=20
QTextView *hello=3Dnew QTextView(
i18n("<H2>Hello World !</H2><BR>This is a simple"
" window with <I><font size=3D5><B>R<font color=3Dred"
" size=3D5>ich </font><font color=3Dblue size=3D5>Text"
"</font></B></I> capabilities<BR>Try to resize"
" this window, all this is automatic !"), "", this );
setCentralWidget( hello );
=20
=20
}=20
=20
void MainWindow::fileOpen()
{
KURL filename =3D KFileDialog::getOpenURL( QString::null, "*", this );
QString msg =3D QString( i18n("Now this app should open the url %1 .") =
).arg(filename.url());
KMessageBox::information( 0, msg, i18n( "Information" ),=20
"fileOpenInformationDialog" );
}
=20
void MainWindow::fileSave()
{
KURL filename=3DKFileDialog::getSaveURL( QString::null, "*", this );
}
</PRE></BLOCKQUOTE>
<HR>
<DIV ALIGN=3DRIGHT>p3.cpp</DIV>
<P>
Este código parece mucho mas complejo, pero no lo es, echemos un vis=
tazo.
<P>
El código en main.cpp no ha cambiado mucho desde p1 o p2. La ú=
;nica=20
diferencia es que ahora creamos un objeto MainWindow en vez de un QPushButt=
on, y que
ahora no especificamos un puntero NULL en el widget padre, ya que se toma p=
or defecto.
<P>
Además, no conectamos ninguna señal aquí, ya que
MainWindow no tiene ninguna señal como <CODE>clicked()</CODE> (ni
tendrí mucho sentido que la tuviera).=20
<P>
<PRE>
class MainWindow : public KMainWindow
{
Q_OBJECT
</PRE>
<P>
En p3.h definimos la clase MainWindow, que hereda de KMainWindow, que es=20
incluida en las kdelibs e incluye todos los métodos necesarios para=
=20
crear una aplicación normal de KDE con un menú, barra de herr=
amientas (toolbar),
barra de estado (status bar), etc. Observe que en versiones anteriores del =
tutorial,
hered=E1bamos de KTMainWindow, pero esta clase se considera obsoleta.
<P>
=46ijémonos que hemos escrito <CODE>Q_OBJECT</CODE> en la declaraci&=
oacute;n de=20
nuestra clase. Q_OBJECT es una macro que declara las variables especiales y=
los
miembros virtuales que necesita el meta-objeto para implementar el mecanism=
o de
señal/slot y otras cosas, y además le dice a moc que este es =
un QObject y que
puede tener señales y/o slots.
<PRE>=20
public slots:
void fileOpen();
void fileSave();
</PRE>=20
<P>
Como aprendimos en p1, los slots son métodos normales, así qu=
e pueden ser
públicos, protegidos o privados (<CODE>public:</CODE>, <CODE>protect=
ed:</CODE>
o <CODE>private:</CODE>) como cualquier otro. La única diferencia se=
ra que debemos=20
especificar <CODE>public slots:</CODE>,<CODE>protected slots:</CODE> o
<CODE>private slots:</CODE>, para que moc sepa que son slots.
<P>
El preprocesador tendrá cuidado de quitar o substituir todas esas ma=
rcas especiales=20
para que no molesten al compilador.
<P>
Veamos ahora el fichero p3.cpp:
<P>
<PRE>
QPopupMenu *filemenu =3D new QPopupMenu;
filemenu->insertItem( i18n( "&Open" ), this, SLOT(fileOpen()) );
filemenu->insertItem( i18n( "&Save" ), this, SLOT(fileSave()) );
filemenu->insertItem( i18n( "&Quit" ), kapp, SLOT(quit()) );
<P>
</PRE>=20
<P>
filemenu es un QPopupmenu, esto es, un menú que contiene "items" (el=
ementos) que el usuario
pulsará para realizar una acción dada.
<P>
Insertamos esos items llamando a <CODE>insertItem</CODE>. El primer par&aac=
ute;metro es el
texto que deberá de estar en el menú, con un caracter & j=
usto delante de la
letra que queramos usar como acceso rápido. Usando i18n nos aseguram=
os que el
texto aparecerá en el lenguaje en el que el usuario tenga configurad=
o su escritorio.
<P>
Cuando el usuario selecciona un elemento, el menú emite una se&ntild=
e;al que puede
(=A1 y debe !) ser conectada a una función para hacer algo. Por conv=
eniencia,
en vez de usar <CODE>connect</CODE>, podemos conectar esta señal dir=
ectamente=20
cuando definimos la entrada del menú. Ésto es lo que hacemos =
en el segundo
y tercer parámetros. Conectamos el elemento de menú <CODE>Ope=
n</CODE> al
slot <CODE>fileOpen()</CODE> en este (<CODE>this</CODE>) objeto, la entrada=
<CODE>Save</CODE>
al slot <CODE>fileSave()</CODE> en este (<CODE>this</CODE>) objeto, y la=20
entrada <CODE>Quit</CODE> al slot <CODE>quit()</CODE> de la aplicació=
;n
(<CODE>kapp</CODE>), tal como hicimos en p1 y p2.
<P>
=46ijémonos en que kapp es una función de conveniencia que pu=
ede ser usada para
acceder a la instancia actual de KApplication.
<P>
<PRE>
QString about =3D
i18n("p3 1.0\n\n"
"(C) 1999-2002 Antonio Larrosa Jimenez\n"
"larrosa@kde.org\t\tantlarr@supercable.es\n"
"Malaga (Spain)\n\n"
"Simple KDE Tutorial\n"
"This tutorial comes with ABSOLUTELY NO WARRANTY\n"
"This is free software, and you are welcome to redistribut=
e it\n"
"under certain conditions\n");
=20
QPopupMenu *helpmenu =3D helpMenu( about );
</PRE>=20
<P>
Primero ponemos esa cadena dentro del objeto QString. QString es una
clase de cadena de texto de propósito general que se usa para manipu=
lar texto de muy
diversas formas. Uno de los principales beneficios de QString es el poder u=
sar
Unicode en la aplicación de forma automática, sin tener que p=
reocuparse de ello.
Ademas provée un mecanismo implícito de compartición d=
e las cadenas que incrementa
su eficiencia, ya que cuando se crea una copia de un QString no se copia re=
almente=20
su contenido hasta que uno de ellos cambia.
<P>
Después creamos otro menú popup, pero usando el miembro helpM=
enu de KMainWindow.
Haciendo eso conseguimos un menú estandard de ayuda, con las entrada=
s para=20
documentación, un diálogo sobre el programa (about), etc. Ade=
más, el
diálogo sobre el programa incluye todo el texto que hemos escrito en=
la
cadena <CODE>about</CODE>.
<P>
<PRE>
KMenuBar *menu =3D menuBar();
menu->insertItem( i18n( "&File" ), filemenu );
menu->insertSeparator();
menu->insertItem( i18n( "&Help" ), helpmenu );
</PRE>=20
<P>
Ya estamos preparados para terminar la creación de nuestro men&uacut=
e;. Primero,
obtenemos la barra de menú usada por nuestra ventana principal usand=
o <CODE>menuBar()</CODE>.
Como no hay barra de menú todav=EDa, este método la crear&aac=
ute; para nosotros
y nos devolverá un objeto KMenuBar vacío que podemos rellenar.
KMenuBar provée un menú estandard de KDE, con una apariencia
común en todas las aplicaciones
<P>
Entonces insertamos los dos QPopupMenus que ya tenemos, con un separador en=
medio,
y ya hemos terminado de crear el menú.
<P>
<PRE>
QTextView *hello=3Dnew QTextView(
i18n("<H2>Hello World !</H2><BR>This is a simple"
" window with <I><font size=3D5><B>R<font color=3Dred"
" size=3D5>ich </font><font color=3Dblue size=3D5>Text"
"</font></B></I> capabilities<BR>Try to resize"
" this window, all this is automatic !"), "", this );
setCentralWidget( hello );
</PRE>=20
<P>
Quería que esta aplicación hiciera algo bonito y simple, asi =
que le vamos
a añadir un widget QTextView. Este widget es un visor bastante &uacu=
te;til de texto
enriquecido (Rich Text), donde podemos especificar el tipo de fuente y colo=
r entre
otras cosas. Despues de crearlo con el texto anterior lo ponemos como el wi=
dget central
( <CODE>centralWidget</CODE> ) de esta ventana.
<P>
Pero, =BFqué es un widget central?. Un widget central es el widget q=
ue el=20
usuario puede ver bajo el menú (o la barra de herramientas si existe=
). Es decir, el=20
widget que muestra el documento que el usuario tiene abierto, o cualquier c=
osa que no es
parte estandar de KMainWindow (esto es, el menú, la barra de herrami=
entas y la de estado).
<P>
<PRE>
KURL filename =3D KFileDialog::getOpenURL( QString::null, "*", this );
</PRE>=20
<P>
Ahora miramos a la implementación del slot de fileOpen. Este c&oacut=
e;digo abre
un diálogo de abrir fichero que permite al usuario abrir un fichero =
existente.
<P>
Los tres parámetros indican el directorio en el que se comienza a bu=
scar (no nos
importa en cual comienza, asi que dejamos el actual por defecto), los filtr=
os
(para ver solo los archivos que cumplen una determinada expresión re=
gular) y el
objeto padre.
<P>
Ahora tenemos el url que el usuario quiere abrir almacenado en <CODE>filena=
me</CODE>.
<P>
Observa que se recomienda encarecidamente el permitir al usuario abrir cual=
quier URL,
no s=F3lo archivos locales. Para esto, hemos utilizado el m=E9todo getOpenU=
RL, que permite
al usuario seleccionar cualquier URL. Mire abajo un ejemplo sobre como usar=
la librer=EDa
KIO.
<P>
<PRE>
QString msg=3DQString( i18n("Now this app should open the url %1 .") ).=
arg(filename.url());
</PRE>=20
<P>
Podemos manipular cadenas con la clase QString, en realidad estamos usando =
esto
para componer el mensaje que vamos a mostrar a continuación (ya que =
abrir un fichero
no se encuentra dentro de los objetivos de este tutorial). El formato es si=
milar al
que se usa con sprintf, pero sin necesidad de preocuparse sobre los tipos d=
e los=20
datos, ya que sólo habrá que usar %1, %2, etc. y despues .arg=
(var1).arg(var2).arg(var3),
etc. Otra cosa buena sobre QString es que no habrá problemas cuando =
la cadena destino
no tenga espacio para la cadena resultante, ya que se reservará mas =
espacio=20
automaticamente.
<P>
Por cierto, filename.url() es un QString que contiene la URL guardada en el=
objeto KURL, o sea,
protocolo+nombre del host+camino+query+todolodem=E1s :-).
<P>
<PRE>
KMessageBox::information( 0, msg, i18n( "Information" ), "fileOpenInfor=
mationDialog" );
</PRE>=20
<P>
Con la clase KMessageBox y sus miembros estáticos, podemos crear una=
variedad
de cajas de mensajes. En este ejemplo, usamos una caja de informació=
n para=20
mostrar qué fichero se debería de haber abierto. El tercer pa=
rámetro es el mensaje
que aparecerá como título de la caja, y el cuarto es un ident=
ificador, que se usa
para almacenar en un fichero de configuración (usualmente ~/.kde/sha=
re/config/p3rc)
si el usuario quiere que no se le muestre mas este diálogo, cosa que=
se decide
usando un checkbox que aparece en el diálogo.
<P>
=A1 Fijémonos en que no hemos escrito ninguna forma de volver a most=
rar ese=20
diálogo de nuevo !. Esto se consigue llamando a <CODE>KMessageBox::e=
nableAllMessages();</CODE>,
pero me parece que sería un buen ejercicio para el lector de este tu=
torial el
añadir un menú que haga esta llamada en p3 :-) .
<P>
<PRE>
KURL filename=3DKFileDialog::getSaveURL( QString::null, "*", this );
</PRE>=20
<P>
=46inalmente, en fileSave llamamos a una función análoga a ge=
tOpenURL, getSaveURL.
<P>
=46ijémonos en que si usamos getOpenURL deberíamos de usar la=
librería KIO para=20
obtener un fichero remoto si eso es lo que quiere el usuario, esto se puede=
hacer de forma
trivial con el siguiente código:
<P>
<PRE>
QString tmpFile;
if( KIO::NetAccess::download( "ftp://ftp.kde.org/myfile.tgz", tmpFile )=
)
{
/* Aqu=ED hacemos lo que queramos con el fichero _local_ guardado en tm=
pFile */
KIO::NetAccess::removeTempFile( tmpFile );
}
</PRE>=20
<P>
Pero esto está fuera del ámbito de este tutorial, aunque pued=
e que lo incremente
en el futuro con un ejemplo de la libreria KIO, libkio.
<P>
Bueno, espero que no fuera demasiado difícil.
<P ALIGN=3D"RIGHT">
<A HREF=3D"p4.html">Siguiente</A>
<A HREF=3D"p2.html">Anterior</A>
<A HREF=3D"index.html">Tabla de Contenidos</A></P>
<HR>
<CENTER>© 1999-2002 <A HREF=3D"mailto:larrosa@kde.org">Antonio Larrosa=
</A></CENTER>
<CENTER>Traducido por <A HREF=3D"mailto:rafael@picasso.scai.uma.es">Rafael =
Larrosa</A> y <A HREF=3D"mailto:larrosa@kde.org">Antonio Larrosa</A></CENTE=
R>
</BODY>
</HTML>
--Boundary-00=_KMYm9C6abutJx2c--