miércoles, 24 de agosto de 2011

Programar rápidamente un navegador web con PyQt

En esta entrada haremos un navegador web muy sencillo y rápido de programar, usando la librería QtWebKit y el componente QWebView de PyQt. Para quien no sabe de lo que hablo, puede leer mis anteriores entradas sobre PyQt donde creamos un Hola Mundo tradicional y luego lo mejoramos con la ayuda del QtDesigner.

Para esta entrada, y en adelante, seguiremos usando el QtDesigner que es la mejor forma de diseñar interfaces gráficas para Qt. También dije que haremos uso de la librería QtWebKit de Qt para el renderizado de las páginas. Con el nombre se deduce que esta librería usa el motor WebKit que, para quien no lo sabe, es el motor que usan Google Chrome y Safari.

Empecemos abriendo el QtDesigner y seleccionando un proyecto nuevo de tipo Main Window


Ahora arrastremos a nuestro formulario un Grid Layout


Hacemos clic derecho sobre el formulario y luego seleccionamos en el menú contextual Lay Out > Lay Out in a Grid. Hemos agregado un layout de tipo grid a nuestro formulario. Ahora arrastramos un Line Edit (campo de texto) y un Push Button (botón) así:


Debajo de estos dos componentes, arrastramos nuestro Web View, que es el componente navegador:


Nombramos nuestros componentes así: al Line Edit lo nombramos leURL, al Push Button btIr y al Web View wvNavegador. También al Push Button le cambiamos el texto por "Ir".

Ahora necesitaremos una función en nuestro formulario, la cual hará que el navegador cargue la URL que escribamos en el Line Edit. Para ello hacemos clic derecho sobre el espacio vacío del formulario y en el menú contextual seleccionamos Change signals/slots para que nos abra el editor de señales. Ya habíamos visto este procedimiento en las anteriores entradas así que debe ser familiar. Agregamos un nuevo slot en nuestra ventana llamado navegar:


Ahora necesitamos conectar nuestro botón Ir a este nuevo slot. Para ello hacemos clic en el botón de edición de señales ubicado en la barra de herramientas:


Así entramos en modo de edición de señales. Hacemos clic sostenido sobre el botón Ir y sin soltar arrastramos el mouse hasta un lugar vacío del formulario. Si se hizo correctamente aparecerá este cuadro de diálogo:


Allí seleccionamos la señal click del botón y el slot navegar del formulario. Con esto ahora cuando se haga clic en el botón, se llamará al slot (función) navegar de nuestro formulario. Esta función la escribiremos en python más abajo.

Ahora, guardemos nuestro diseño con el nombre navegador.ui, y ya estamos listos para exportarlo a python. Recordemos el procedimiento:
  1. Abrimos una ventana de terminal (o consola) en el directorio donde guardamos el archivo Ui.
  2. Ejecutamos la orden pyuic4 navegador.ui -o navegador_gui.py. Si no funciona es que necesita configurar el pyuic4 como lo describo en esta entrada, o bien, puede llamarlo desde su ubicación completa (sólo en Windows), por ejemplo en mi caso: C:\Python25\Lib\site-packages\PyQt4\bin\pyuic4 navegador.ui -o navegador_gui.py (porque uso Python 2.5).
Ya tenemos un archivo navegador_gui.py que contiene el diseño ya exportado. Luego creamos nuestro script principal que llamaremos navegador.py. Lo abrimos para escribir lo siguiente:

from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtWebKit import *
from navegador_gui import Ui_MainWindow
import sys

class Navegador(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self,None)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
    def navegar(self):
        sUrl = str(self.ui.leURL.text())
        if not sUrl.startswith('http://'):
            sUrl = 'http://'+sUrl
        url = QUrl(sUrl)
        self.ui.wvNavegador.load(url)

app = QApplication(sys.argv)
nav = Navegador()
nav.show()
sys.exit(app.exec_())

El código es muy similar al que ya hicimos en la entrada anterior. Como vemos, hemos agregado la función navegar que se corresponde con el slot que agregamos al formulario y que asociamos al botón Ir. Allí pondremos el código que se ejecutará cuando se hace clic en dicho botón.

Entre lo nuevo podemos ver que hemos importado las librerías QtWebKit y QtCore. La función __init__ es igual a nuestro anterior proyecto. Lo diferente es la función navegar que agrega lo siguiente:

#Obtenemos la dirección que escribió el usuario en
#el Line Edit
sUrl = str(self.ui.leURL.text())
#Si la drección no empieza con http:// se lo agregamos
if not sUrl.startswith('http://'):
    sUrl = 'http://'+sUrl
#Creamos un QUrl con la dirección...
url = QUrl(sUrl)
#Y la cargamos en el navegador
self.ui.wvNavegador.load(url)

Debemos tener presente que los componentes con texto en PyQt (como el Line Edit del ejemplo) no devuelven un str sino un QString, por ello tenemos que convertirlo a un string de python con str(elQString).

Con este sencillo código ya tenemos un navegador funcional. Ejecutémoslo con la línea de comando python navegador.py. Escribimos una dirección en el campo de texto (el Line Edit) y pulsamos el botón Ir:


Sólo para Windows:


Si vamos a la siguiente dirección: http://www.adobe.com/software/flash/about/ veremos una página sin animación Flash:


Tampoco podremos ver videos en Youtube :p . Esto es porque nuestro navegador no está cargando los plugins de WebKit. Para que los cargue (entre ellos el Flash Player) debemos agregar lo siguiente después del self.ui.setupUi(self):

self.ui.wvNavegador.settings().setAttribute(QWebSettings.PluginsEnabled,True)

Hay más opciones para explorar en la clase QWebSettings. El código completo queda así:

from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtWebKit import *
from navegador_gui import Ui_MainWindow
import sys

class Navegador(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self,None)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.wvNavegador.settings().setAttribute(QWebSettings.PluginsEnabled,True)
    def navegar(self):
        sUrl = str(self.ui.leURL.text())
        if not sUrl.startswith('http://'):
            sUrl = 'http://'+sUrl
        url = QUrl(sUrl)
        self.ui.wvNavegador.load(url)

app = QApplication(sys.argv)
nav = Navegador()
nav.show()
sys.exit(app.exec_())

Al ejecutarlo:


Voilà! Nuestro navegador carga animaciones Flash (y otros plugins) sin problemas.

En próximas entradas extenderemos un poco este navegador, agregándole nuevas funcionalidades y más adelante conectaremos a Python con Javascript y Flash.

1 comentario:

Si deseas extender esta entrada, por favor hazlo