fernando | veamos |
antlarr | Los que esteis esperando para la charla sobre programación con KDE podeis ir bajándoos el tutorial que hay en http://perso.wanadoo.es/antlarr/bin/kdetutorial-1.1.2.tar.bz2 |
fernando | En breves instantes va a comenzar la conferencia sobre KDE |
fernando | Recuerden que más tarde teneoms una interesante ponencia sobre comercio electrónico y linux en perú |
fernando | Si les parece, empezamos |
fernando | Hola a todos |
fernando | Ahora tenemos el placer de presentar la conferencia de Antonio Larrosa. |
fernando | Es un desarrollador de KDE, proyecto con el que colabora desde 1997. |
fernando | Estudia matemáticas en la Universidad de Málaga |
fernando | Queremos agradecer a todos su presencia aquí, y a Antonio muy |
fernando | esspecialmente por haber preparado esta interesante conferencia. |
fernando | Esta |
fernando | época es especialmente mala para los estudiantes, con muchos exámenes y |
fernando | todas esas cosas desagradables ;) |
fernando | Hoy nos va a hablar de Desarrollo de aplicaciones en KDE |
fernando | Sr. Larrosa... |
antlarr | Muchas gracias fernando |
antlarr | Buenas noches a todos |
antlarr | Como ya ha dicho Fernando, voy a tratar de explicar cómo se programa en KDE |
antlarr | para ello, voy a exponer primero una introducción sobre programación en Qt |
antlarr | y después pasaré a explicar un tutorial que he escrito y que podeis encontrar en |
antlarr | http://perso.wanadoo.es/antlarr/bin/kdetutorial-1.1.2.tar.bz2 |
antlarr | Si quereis verlo "online" podeis acceder a http://perso.wanadoo.es/antlarr/tutorial/index.html |
antlarr | En el tutorial empezaré desde cero, y cuando lo terminemos habremos construido dos aplicaciones |
antlarr | una es un navegador de internet con soporte HTML4, CSS1 y 2, Flash, Javascript, etc. |
antlarr | (incluso soporte para historial) |
antlarr | y la otra aplicación es un gestor de "favoritos" que se comunica con el navegador |
antlarr | para gestionarlos |
antlarr | todo eso lo haremos en sólo 9 pasos (agrandando poco a poco el programa), e intentaré explicar linea a linea como funciona |
antlarr | sólo necesitareis un poco de experiencia en C++ (si sabeis C, creo que podeis enteraros de algo también :) ) |
antlarr | Si quereis hacer alguna pregunta, haré una parada al final de cada paso para que me pregunteis sobre lo que estaba hablando |
antlarr | Además, al final haremos otro turno de preguntas más generales y para lo temas que se os hayan quedado "atascados" |
antlarr | Bien, empezaré primero por explicar sobre Qt |
antlarr | Como la mayoría de vosotros sabréis, Qt es una librería multiplataforma desarrollada por Trolltech, y que está disponible para entornos Unix bajo la GPL (además de otras licencias para uso comercial) |
antlarr | Escribiendo un único código fuente, podeis compilar el mismo programa en Linux, Windows, Mac e incluso para dispositivos PDA |
antlarr | Por ello, han desarrollado una extensa gama de clases para casi todo |
antlarr | Por ejemplo, los que programeis en C estaréis acostumbrados a usar "char *" para vuestras cadenas de texto |
antlarr | y los que uséis C++ con la STL, usareis "string" |
antlarr | Qt implementa una clase que se llama QString que sirve para almacenar una cadena de texto |
antlarr | La gracia de esta clase es que obtenemos "gratuitamente" (en el sentido de "sin esfuerzo por nuestra parte") una cadena de texto que puede contener caracteres unicode |
antlarr | y que es muy fácil de usar |
antlarr | Además, tiene cosas como "shallow copy" que significa que cuando copias una cadena en otra, lo que hace realmente es copiar una referencia de forma que es mucho más rápido que copiar la cadena entera "de verdad" |
antlarr | así, luego implementa el "copy on change" para hacer la copia real cuando alguna de las cadenas es modificada |
antlarr | Otros ejemplos de clases útiles son QChar, que guardan caracteres. |
antlarr | QList <template> nos sirve para guardar una lista de objetos |
antlarr | (de punteros a objetos) |
antlarr | Es una lista doblemente enlazada que podemos utilizar muy facilmente. Por ejemplo: |
antlarr | QList <MiObjeto> lista(); |
antlarr | lista.append(unobjeto); |
antlarr | lista.append(otroobjeto); |
antlarr | además, hay iteradores para recorrer la lista. |
antlarr | Por otra parte, hay clases que en vez de guardar una lista de punteros a objetos, guardan una lista de objetos en sí (por valor). |
antlarr | Arrays, Pilas (Stacks), etc. |
antlarr | Por otra parte, tenemos otra colección de objetos que implementa Qt que son más específicos |
antlarr | el más básico de estos es QObject |
antlarr | Como ya he comentado, Qt extiende el lenguaje definido por C++ para añadir nuevas funcionalidades |
antlarr | Algunas de las más importantes son el soporte de señales/slots, y el soporte de propiedades (por nombrar sólo algunos ejemplos) |
antlarr | Estas funcionalidades las añade por medio de la clase QObject, que es donde se implementa este soporte. |
antlarr | Algunos de vosotros os preguntareis qué son señales y slots, así que voy a intentar dar una breve descripción. |
antlarr | Generalmente, en los sistemas de ventanas, las aplicaciones realizan tareas de acuerdo a determinados eventos |
antlarr | el gestor de ventana (o XWindows en nuestro caso) genera los eventos y en nuestro código tenemos un enorme bloque switch(evento) { .... }; que trata todos los posibles eventos |
antlarr | en vez de realizar esto así, nosotros vamos a hacerlo de una forma más cómoda y mucho más extensible (el código que se obtiene es realmente más reutilizable), usando señales |
antlarr | Las señales son eventos que las clases generan cuando cambian de estado, y los slots son funciones (funciones miembros de cualquier clase) a las que se conectan las señales |
antlarr | de esta forma, en nuestro código "conectamos" una señal con un slot, de forma que cuando el objeto primero cambie su estado de alguna forma, el objeto segundo haga algo. |
antlarr | Por ejemplo, |
antlarr | Supongamos que tenemos un botón (clase QPushButton) que queremos que descargue el correo cada vez que se pulse. |
antlarr | Y tenemos una función (en un objeto nuestro "lectorDeCorreo" ) que descarga el correo |
antlarr | lo único que tenemos que hacer es tratar a esa función como un slot y poner en nuestro código |
antlarr | connect(boton, SIGNAL(clicled()), lectorDeCorreo, SLOT(descargaCorreo())); |
antlarr | connect(boton, SIGNAL(clicked()), lectorDeCorreo, SLOT(descargaCorreo())); |
antlarr | :-) |
antlarr | como veis, el botón genera una señal (con nombre "clicked()" ) cada vez que es pulsado (de hecho, pulsado y soltado, ya que hay otras señales "pressed()" y "released()" ) |
antlarr | Además, si queremos que además de descargar el correo, el botón haga sonar un fichero wav (cosa que hacemos en nuestra función "tocaMusica()" ) |
antlarr | sólo tenemos que añadir otra conexión al botón, ya que podemos tener tantas conexiones de una misma señal a cuantos slots queramos |
antlarr | también podemos tener muchas señales conectadas a un mismo slot |
antlarr | la gracia de esto es que el botón no sabe para qué se utilizan las señales, simplemente las emite y "se olvida", y los slots no saben por qué se han llamado, simplemente ejecutan su función. Con lo que se consigue muchísima más reusabilidad de objetos que con otros métodos |
antlarr | supongo que alguno de vosotros se preguntará por qué he usado paréntesis así "()" al final de cada nombre de señales o slots |
antlarr | Lo he hecho así, porque en realidad ambas cosas no son más que funciones, que en este caso no tenían parámetros, pero que podrían tenerlos (y de cualquier tipo, no sólo de tipos básicos) |
antlarr | por ejemplo, una barra de scroll (o barra de desplazamiento) tiene un valor dentro de un rango. |
antlarr | cuando el usuario mueve la barra, el objeto genera una señal llamada "valueChanged(int)" |
antlarr | que podemos conectar a una función de un objeto nuestro que se llame por ejemplo mueveLaPantalla(int v); |
antlarr | Bien, pues toda esta funcionalidad está implementada en QObject, y por tanto tenemos que heredar de ese objeto si queremos tener señales/slots en un objeto nuestro. |
antlarr | De QObject hereda otra clase muy importante que se llama QWidget |
antlarr | un QWidget es cualquier cosa que veais en la pantalla de vuestro ordenador, un botón, un menú, una barra de herramientas, una barra de scroll, la barra de título de vuestras ventanas, etc. |
antlarr | QWidget es la base de la que heredan por tanto clases como QButton, QMenuBar, QToolBar, QScrollBar, etc. |
antlarr | Y bueno, creo que ya estoy acabando la introducción |
antlarr | hay alguna pregunta antes de que pasemos a hacer nuestro primer programa ? |
fernando | preguntas |
fernando | podrías comentar por encima algunos modelos alternativos al que acabas de contarnos ? |
antlarr | si quieres programar en KDE, es el único modelo a seguir :) |
fernando | jaja |
fernando | me refería a la competencia |
antlarr | en Windows por ejemplo, según tengo entendido se sigue el modelo que ya he explicado basado en eventos |
pekesan | si, pero hay ke dar bastantes mas vueltas para manejar los eventos en windows |
pekesan | ;P |
antlarr | sí, hay que hacer muchas definiciones (tipo #define) generalmente en Windows :) |
antlarr | es más fácil si usas el propio API de vuestro programa como "mensajería" |
antlarr | en Gtk por ejemplo creo que usan algo parecido a señales y slots |
antlarr | pero prefiero no hablar del tema porque no he programado practicamente nada en Gtk |
antlarr | Una cosa muy importante de Qt es la estandarización de los nombres que una vez que te acostumbras es muy cómoda. |
lucre | donde se puedo dar clases particulares? |
antlarr | Por ejemplo, sabes que si quieres obtener el ancho de un objeto de tipo QPixmap, sólo tienes que llamar a mipixmap.width() |
antlarr | es decir, siempre vas a utilizar el nombre de la "propiedad" que quieres obtener |
antlarr | nada de unas veces width(), otras veces Width(), getWidth(), get_width(), etc. |
fernando | eso me recuerda otra pregunta, relativa a algo que dijiste antes |
fernando | hablaste de Qstring (o algo asi) |
pekesan | klaro, todas derivan de QObject no...supongo ke se redefine el metodo no? |
antlarr | siempre, cuando se quiere obtener un valor, se llama a una función que tiene el nombre de la propiedad, y cuando se quiere establecer, se llama a set... seguido de la propiedad (por ejemplo, setWidth(nuevoAncho) ) |
fernando | las funciones de manejo de cadenas en qt, son robustas, consistentes y todo eso? |
fernando | o se parecen a las de C ? |
antlarr | son _muy_ robustas :) |
antlarr | pekesan: un momento |
antlarr | por ejemplo, ya he comentado que soportan unicode, soportan escritura bidireccional, y como he comentado son _muy_ rápidas. |
antlarr | Por supuesto, han tenido en cuenta que hay casos en los que no hace falta unicode (que como sabeis, utiliza 16 bits por carácter en vez de 8) y también hay otra clase llamada QCString que es más parecida a lo que sería un char * |
antlarr | Además, QString facilita mucho el tema de las traducciones del software a otros idiomas |
antlarr | ya que puedes poner por ejemplo: |
antlarr | QString micadena("this is test number %1"); |
antlarr | micadena.arg(numero); |
antlarr | perdón, quería decir, al principio: |
antlarr | QString micadena(tr("this is test number %1")); |
antlarr | (para que lo traduzca :) ) |
antlarr | así, al programador le da igual si la cadena en el lenguaje de Yoda se traduce como "el test numero %1 éste es" |
antlarr | ya que QString se encarga de cambiar %1 esté donde esté. |
antlarr | Por otra parte, y contestándote fernando más directamente, QString no tiene problemas de desbordamiento con los equivalentes a sprintf y todo eso, con lo que se eliminan muchos problemas de seguridad |
antlarr | pekesan: contestando tu pregunta, si casi todas las clases heredan de QObject |
antlarr | pero ni QString por ejemplo, ni los tipos de datos básicos lo hacen porque realmente no necesitan el manejo de señales |
antlarr | ¿alguna pregunta más? |
antlarr | Bien, pues continuamos con el paso 1 : un "Hola Mundo" escrito en Qt |
antlarr | Es un programa que muestra un botón con el texto "hola mundo" y que se cierra cuando lo pulsamos. |
antlarr | El programa nos va a caber entero en un fichero: |
antlarr | #include <qapplication.h> |
antlarr | #include <qpushbutton.h> |
antlarr | int main( int argc, char **argv ) |
antlarr | { |
antlarr | QApplication a( argc, argv ); |
antlarr | QObject::connect( hello, SIGNAL(clicked()), &a, SLOT(quit()) ); |
antlarr | a.setMainWidget( hello ); |
antlarr | return a.exec(); |
antlarr | } |
antlarr | eso es todo |
antlarr | los include los escribimos para poder utilizar esas clases, así que la primera linea del programa en sí es |
antlarr | QObject::connect( hello, SIGNAL(clicked()), &a, SLOT(quit()) ); |
antlarr | a.setMainWidget( hello ); |
antlarr | return a.exec(); |
antlarr | } |
antlarr | QApplication a( argc, argv ); |
antlarr | ¿Qué es lo que hace QApplication? |
antlarr | Bien, QApplication es un objeto que debe existir siempre en cualquier aplicación que hagamos y que gestiona aspectos básicos de cualquier programa |
antlarr | por ejemplo, los parámetros estándares de XWindows como -geometry, etc. |
fernando | (programa en http://perso.wanadoo.es/antlarr/tutorial/p1.html ) |
antlarr | para ello, creamos el objeto a y al constructor le pasamos los parámetros argc y argv que son los que teníamos de nuestro main |
antlarr | (gracias fernando, se me había olvidado :) ) |
antlarr | En la segunda linea |
antlarr | lo que hacemos es crear un objeto de tipo QPushButton, es decir, un botón que se puede pulsar |
antlarr | (además de botones que se pueden pulsar, hay botones que tienen dos estados (QCheckBox) o botones que se agrupan y sólo uno de ellos puede estar activo a la vez (QRadioButton) ) |
antlarr | El primer parámetro es el texto que va a contener ("Hello world!") |
antlarr | y el segundo parámetro es el "padre" de este botón (en este caso, 0 o sea, sin padre, lo que significa que debe aparecer como una ventana independiente) |
antlarr | Recuerdo que se dice que un widget (un botón es un widget al fin y al cabo) es hijo de otro si está dentro de otro. |
antlarr | (al que se considera, padre) |
antlarr | llama a la función resize del botón para cambiarle el tamaño a una cosa adecuada para el texto que estamos escribiendo |
antlarr | con QObject::connect( hello, SIGNAL(clicked()), &a, SLOT(quit()) ); |
antlarr | lo que hacemos es conectar la señal "clicked()" del botón hello al slot "quit()" de nuestra aplicación a. |
antlarr | Es decir, cierra la aplicación cuando el botón se pulse. |
antlarr | a.setMainWidget( hello ); le especifica al objeto QApplication que hello va a ser nuestro widget principal |
antlarr | es decir, el bucle de eventos que va a llamar a los slots apropiados cada vez que ocurra algo en nuestra aplicación, etc. |
antlarr | los que hayais bajado el tutorial, supongo que ya lo habreis compilado y lo habreis probado |
antlarr | ¿hay alguna pregunta al respecto? |
fernando | preguntas ? |
antlarr | ¿ha sido muy dificil? ¿facil? ¿seguimos? |
antlarr | Pues sigamos con el paso 2 donde vamos a hacer el mismo programa, pero utilizando las librerías de KDE |
antlarr | Las librerías de KDE lo que hacen es extender Qt allí donde nos hace falta a nosotros para hacer la programación más fácil todavía |
antlarr | (hay que recordar que KDE es un proyecto de voluntarios de todo el mundo, con lo que intentamos hacer que sea lo más divertido posible :) ) |
antlarr | El programa ahora es |
antlarr | #include <kapp.h> |
antlarr | #include <klocale.h> |
antlarr | #include <qpushbutton.h> |
antlarr | int main( int argc, char **argv ) |
antlarr | { |
antlarr | KApplication a( argc, argv , "p2"); |
antlarr | QObject::connect( hello, SIGNAL(clicked()), &a, SLOT(quit()) ); |
antlarr | a.setMainWidget( hello ); |
antlarr | return a.exec(); |
antlarr | } |
antlarr | La primera diferencia está en que en vez de QApplication, usamos un KApplication que se encarga de más tareas todavía que QApplication (por ejemplo, poner los colores y el tema definidos por el usuario, etc.) |
antlarr | Además, en vez de utilizar directamente "Hello World!", el texto que utilizamos ahora es el que devuelve la función i18n, es decir, la traducción del texto "Hello World!" |
antlarr | de hecho, es la traducción al idioma que el usuario ha configurado en su panel de control |
antlarr | como estamos utilizando un texto que desconocemos en principio, no sabemos como de larga va a ser la cadena en cualquier idioma, con lo que no podemos hacer un resize como antes |
antlarr | Lo que usamos es "setAutoResize" para hacer que el botón se ajuste automaticamente al texto que contiene. |
antlarr | y el resto es igual que antes. |
antlarr | El programa que obtenemos ahora es un botón que se integra en nuestro escritorio (ya que usa el tema y colores especificados por el usuario para todos los programas) y que muestra el texto "hola mundo !" en el idioma en que el usuario tiene configurado su sistema |
antlarr | ¿alguna pregunta? |
antlarr | Espero que no os hayais dormido todavía, porque poco a poco vamos llegando a cosas interesantes :) |
antlarr | en el siguiente paso vamos a añadir un menú y texto con formato (fijo) |
antlarr | y en el siguiente (p4) vamos a hacer un navegador de internet casi con el mismo soporte que IE 6.0 (y en muchos casos superior a IE5.5 o a Netscape 4.x) |
antlarr | bueno, pues sigamos. |
antlarr | El paso 3 lo he dividido en varios ficheros |
antlarr | main.cpp que es casi como antes: |
antlarr | #include <kapp.h> |
antlarr | #include "p3.h" |
antlarr | int main( int argc, char **argv ) |
antlarr | { |
antlarr | KApplication a( argc, argv, "p3"); |
antlarr | a.setMainWidget( window ); |
antlarr | return a.exec(); |
antlarr | } |
antlarr | p3.h : |
antlarr | #include <kmainwindow.h> |
fernando | vaya |
fernando | enseguida volverá el conferenciante ;) |
antlarr | Bueno, MainWindow es el objeto que vamos a utilizar como nuestra ventana principal |
antlarr | En p3.h ponemos: |
antlarr | #include <kmainwindow.h> |
antlarr | class MainWindow : public KMainWindow |
antlarr | { |
antlarr | Q_OBJECT |
antlarr | public: |
antlarr | MainWindow ( const char * name ); |
antlarr | public slots: |
antlarr | void fileOpen(); |
antlarr | void fileSave(); |
antlarr | }; |
antlarr | y en p3.cpp : |
antlarr | #include "p3.h" |
antlarr | #include <kfiledialog.h> |
antlarr | #include <kapp.h> |
antlarr | #include <kmenubar.h> |
antlarr | #include <klocale.h> |
antlarr | #include <kmessagebox.h> |
antlarr | Bueno, podeis ver el resto del programa en http://perso.wanadoo.es/antlarr/tutorial/p3.html :) |
fernando | ;) |
antlarr | Como decía, ahora vamos a usar un MainWindow que hereda de KMainWindow como nuestra ventana principal |
antlarr | KMainWindow se va a encargar de gestionar por nosotros la barra de menú, de herramientas, la barra de estado, y el "área de documentos" (lo que queda entre la barra de herramientas y la de estado) |
antlarr | Una de las nuevas cosas que hacemos es |
antlarr | public slots: |
antlarr | void fileOpen(); |
antlarr | void fileSave(); |
antlarr | en p3.h |
antlarr | esto especifica a Qt que fileOpen y fileSave no sólo son funciones públicas de nuestro objeto, sino que deben ser tratadas como slots a los que se pueden conectar señales |
antlarr | algunos os preguntareis si esto no quiere decir que hemos dejado de programar en C++ "estandar" y estamos programando en una derivación de C++ |
antlarr | esto sucede "sólo en parte" |
antlarr | Como comenté antes, Qt extiende a C++, en este sentido añade una nueva sintaxis que sólo el precompilador de Qt (moc, o "Meta Object Compiler" ) entiende |
antlarr | lo que moc hace es analizar nuestros ficheros .h (sólo para las clases que heredan de QObject) y genera código C++ estandar en otro fichero |
antlarr | sólo tenemos que añadir este fichero a nuestro proyecto y ya tenemos un programa completo en C++ estandar |
antlarr | ya que cuando "public slots:" pasa por el precompilador de C++ (el cpp estandar), se queda en "public:" que es lo que realmente llega a nuestro compilador de C++ (g usualmente) |
antlarr | ya que cuando "public slots:" pasa por el precompilador de C++ (el cpp estandar), se queda en "public:" que es lo que realmente llega a nuestro compilador de C++ (g++ usualmente) |
antlarr | Bien, las lineas de tipo |
antlarr | deberían estar claras (añaden menús y hacen que cuando el usuario los seleccione, llame a este objeto (this) al slot fileOpen() ) |
antlarr | QTextView es una clase que permite mostrar texto con formato (pseudo html) |
antlarr | y setCentralWidget hace que ese QTextView sea precisamente el widget que aparezca como principal en nuestra ventana |
antlarr | O mejor dicho, abrir una URL cualquiera. Esto lo hacemos así porque con KDE se puede acceder desde cualquier aplicación a ficheros que estén en cualquier sitio de internet |
antlarr | Por ejemplo, abrir una página web en un editor de texto es tan fácil como abrir la ventana de "abrir fichero" y especificar en el nombre del fichero "http://mi.servidor/mi/pagina.html" |
antlarr | ¿Alguna pregunta respecto a esta aplicación? |
antlarr | (voy más rápido porque me gustaría llegar al menos al siguiente paso que es donde hacemos el navegador) |
fernando | tengo una pregunta |
fernando | si entiendo bien |
fernando | esto ya no es c++ sino algo que se traduce a c++ |
fernando | es correcto ? |
antlarr | Es C++ |
pekesan | puedo preguntar? |
antlarr | el compilador debe compilar p3.cpp (p3.h) y _además_ p3.moc (generalmente, se llama p3_moc.cpp) |
antlarr | lo que pasa es que en las cabeceras de Qt hay una linea parecida a: |
antlarr | #define slots |
fernando | ajá |
antlarr | es decir, que define slots como "nada" |
pekesan | ke es eso del formato pseudo-html? |
antlarr | de forma que cuando el compilador llega a "public slots:" lo que lee es "public:" |
antlarr | pekesan: Admite etiquetas como <P>, <font>, <BR>, <I>, <H1>, <IMG> etc. pero no cosas más avanzadas |
antlarr | para eso hace falta un motor de renderizado de páginas html, que es lo que usamos en p4 |
antlarr | pasemos a p4 |
antlarr | podeis verlo en http://perso.wanadoo.es/antlarr/tutorial/p4.html |
antlarr | Las diferencias con p3 son: |
antlarr | en p4.h añadimos: |
antlarr | public slots: |
antlarr | void changeLocation(); |
antlarr | void openURLRequest(const KURL &url, const KParts::URLArgs & ); |
antlarr | private: |
antlarr | QLineEdit *location; |
antlarr | KHTMLPart *browser; |
antlarr | QLineEdit es una clase que permite al usuario editar una linea de texto |
antlarr | la vamos a utilizar para que el usuario nos diga la página que queremos ver |
antlarr | KHTMLPart es un widget que se implementa en las librerías de KDE y que permite ver una página web |
antlarr | changeLocation será el slot que se llame cuando el usuario pulse la tecla <enter> (o <intro>) y que cogerá el texto de la linea de edición para saber qué página abrir |
antlarr | Si vemos p4.cpp, changeLocation es sólo una linea: |
antlarr | y openURLRequest es una función que se llamará cuando el usuario pulse en un enlace que haya en una página web |
antlarr | Es decir, es una petición para que abramos una página determinada (indicada en el parámetro url). Podemos ignorar el segundo parámetro de esta función porque se usa para cosas más avanzadas |
antlarr | El código de esa función queda: |
antlarr | changeLocation(); |
antlarr | es decir, pone el texto en la barra de edición y llama a la función anterior (changeLocation() ) |
antlarr | Nos fijamos ahora en como hemos construido nuestros objetos y cómo hemos hecho las conexiones de las señales: |
antlarr | connect( location , SIGNAL( returnPressed() ), |
antlarr | this, SLOT( changeLocation() ) ); |
antlarr | SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ), |
antlarr | this, SLOT( openURLRequest(const KURL &, const KParts::URLArgs & ) ) ); |
antlarr | como veis es todo completamente lógico, y yo diría que incluso legible para alguien que se añada ahora mismo a nuestra conversación. |
antlarr | vbox es un objeto de tipo QVBox |
antlarr | los QVBox (y QHBox) son widgets que permiten especificar una disposición de los widgets hijos |
antlarr | son "invisibles" por decirlo de alguna manera |
antlarr | y "sólo" se utilizan para que automaticamente, los widgets hijos se añadan uno debajo de otro |
antlarr | El resultado lo podeis ver en http://perso.wanadoo.es/antlarr/tutorial-umeet.jpg |
antlarr | (de hecho, esa imagen es de p9, pero es muy parecido a p4) |
antlarr | Ahí podeis ver a p9 navegando por la página web de umeet |
antlarr | Si quereis continuar viendo el tutorial, podeis visitar la página web en http://perso.wanadoo.es/antlarr/tutorial.html |
antlarr | Recordad que el tutorial continúa con comunicación entre procesos usando DCOP, y muchas más cosas interesantes :) |
antlarr | espero que hayais pasado un rato agradable al igual que yo :) |
antlarr | muchas gracias por vuestra atención |
fernando | plas plas plas plas plas plas plas plas plas plas plas plas |
Oroz | gracias a ti Antonio :) |
fernando | plas plas plas plas plas plas plas plas plas plas plas plas |
fernando | plas plas plas plas plas plas plas plas plas plas plas plas |
fernando | plas plas plas plas plas plas plas plas plas plas plas plas |
fernando | plas plas plas plas plas plas plas plas plas plas plas plas |
Ston | antlarr: disculpa los "plas" de ahorita ;) |
Ston | plas plas plas plas plas plas plas plas plas plas plas |
Ston | plas plas plas plas plas plas plas plas plas plas plas |
Ston | plas plas plas plas plas plas plas plas plas plas plas |
fernando | ahora es el momento ston ;) |
Ston | plas plas plas plas plas plas plas plas plas plas plas |
Ston | plas plas plas plas plas plas plas plas plas plas plas |
fernando | andele |
antlarr | Ston: :-) |
Oroz | jeje |
fernando | Este seguramente es un buen momento para agradecer a todos ustedes su asistencia |
Ston | X) |
fernando | y a Antonio Larrosa por su intersantísimo mini-curso |
fernando | No olviden que en breves instantes comenzará la conferencia sobre comercio electrónico y la experiencia en Perú |
antlarr | ha sido un placer. Espero que de esta charla aparezcan nuevos programadores que serán por supuesto bienvenidos en las listas de desarrollo de KDE. |
antlarr | (si alguien tiene alguna pregunta, por favor, hacédmela en privado para no molestar a la próxima conferencia) |
Oroz | cr0ut: estás? |
bodhi | ola |
antlarr | Buenas noches |