Herramientas de usuario

Herramientas del sitio


fw:pyqt4

¡Esta es una revisión vieja del documento!


PyQt 4

PyQt es un binding de Python para el framework de aplicaciones de Nokia Qt.
Para Python actualmente existen el PyQt 4 y el PyQt 3.
Los principales módulos son:

  • QtCore, el núcleo con las clases que no corresponden a GUIs (eventos, threads, ficheros, expresiones regulares…).
  • QtGui que contiene la mayoría de las clases para crear GUIs.
  • QtHelp que contiene clases para crear visores de “ayudas” para las aplicaciones.
  • QtNetwork que contiene clases para escribir UDP\TCP clientes y servidores.
  • Además de QtOpenGL, QtScript (intérprete de JavaScript), QtSql, QtSvg, QtTest (para unit tests), QtWebKit (para implementar un navegador web), QtXml, QtXmlPatterns (para modelos de datos Xml), QtMultimedia, QtDesigner (para utilizar el diseñador de Qt), QAxContainer (para implementar objetos COM y ActiveX)…

Y también algunas utilidades como:

  • pyuic4, que convierte las GUIs creadas con el Qt Designer en código Python.
  • pyrcc4 que agrega recursos en un fichero.
  • pylupdate4 para trabajar con strings de lenguaje.



La documentación para Qt4 se encuentra en http://doc.qt.nokia.com/4.0/ y para PyQt4 en http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/classes.html.

Aplicaciones con PyQt4

Básico

QApplicaction

Los objetos que representan aplicaciones basadas en Qt se crean a partir de la clase QtGui.QApplication, una vez tenemos uno de estos objetos podremos gestionar los eventos de la aplicación, su flujo de control, su configuración…
Para construir un objeto lo podemos hacer a partir de su constructor __init__ (self, list-of-str argv), este inicializará el sistema de ventanas Qt, la aplicación y tomará como argumentos los argumentos pasados a la aplicación. Si quisieramos construir una aplicación podríamos utilizar el constructor __init__ (self, list-of-str argv, bool GUIenabled) asignando GUIenabled a false·
El método int QApplication.exec_ () crea y entra en el bucle principal de la aplicación hasta que se llame a quit() o a exit(), entonces devuelve el valor que se pasó a exit() o 0 si se llamó a quit().

app = QtGui.QApplication(sys.argv)
...
sys.exit(app.exec_())

QWidget's

La clase QWidget es la clase base para todos los objetos que permiten formar un entorno gráfico. Recibe los eventos del mouse, del keyboard, del sistema, de pintado… Todo widget es rectangular y están ordenado (a la hora de dibujarse por pantalla) en un z-order, aunque está delimitado por el widget-padre que lo contiene, el único widget que no tendría padre sería una ventana; generalmente las ventanas tienen “un frame” y una barra de título (en Qt puedes encontrarte clases como QMainWindow o QDialog que son las más adecuadas para este tipo de widgets).
Cada constructor de un widget acepta uno o dos argumentos por defecto:

  1. QWidget *parent = 0, es el padre del widget creado. Si es 0 (por defecto), el widget será una venta, si no el widget creado será un hijo del indicado y estará delimitado por este.
  2. Qt.WindowFlags f = 0 asigna las flags de ventana.
import sys
from PyQt4 import QtGui
 
app = QtGui.QApplication(sys.argv)
widget = QtGui.QWidget()
widget.resize(250, 150)
widget.setWindowTitle('simple')
btn = QtGui.QPushButton("Press", widget)
widget.show()
 
sys.exit(app.exec_())

Podemos también hacerlo OO:

class MyWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        quitbutton = QtGui.QPushButton('Close', self)
        self.setCentralWidget(quitbutton)
qApp = QtGui.QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(qApp.exec_())

Eventos (signal & slots)

Los signals se emiten por un objeto cuando algo cambia en él, se podría decir que son los eventos. Cuando un signal es emitido los slots que se conectan a él se ejecutan como si fuese una llamada a función, si hubiese varios conectados se ejecutarían en un orden arbitrario.
El formato (general) para realizar una conexión signal-slot es:

QtCore.QObject.connect(objeto, QtCore.SIGNAL("método"), nombre_funcion)

Por ejemplo:

import sys
from PyQt4 import QtCore
from PyQt4 import QtGui
 
def bclicked():
    print "Button Clicked"
 
qApp = QtGui.QApplication(sys.argv)
 
button = QtGui.QPushButton("Click Me")
QtCore.QObject.connect(button, QtCore.SIGNAL('clicked()'), bclicked)
button.show()
 
sys.exit(qApp.exec_())

Aunque a partir de la versión 4 también existe la siguiente forma (a partir de una propiedad creada con el mismo nombre que el signal):

button.clicked.connect(clicked) 

U otra forma, utilizando el decorador signal:

button = QtGui.QPushButton("Click Me")
button.show()
 
@button.clicked.connect
def btnclicked():
    print "Button Clicked"

Para crear nuestros propios Signals:

import sys
from PyQt4 import QtCore
from PyQt4 import QtGui
 
class MyWindow (QtGui.QWidget):
    mySignal = QtCore.pyqtSignal()
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.button = QtGui.QPushButton("Click Me", self)
        self.button.clicked.connect(self.btnclicked)
        self.i = 0
 
    def btnclicked(self):
        print "Button Clicked"
        self.i = self.i + 1
        if (self.i > 2):
            self.mySignal.emit()
 
def myTooMuch():
    print 'Too Much'
 
qApp = QtGui.QApplication(sys.argv)
w = MyWindow()
w.mySignal.connect(myTooMuch)
w.show()
sys.exit(qApp.exec_())

Para enviar parámetros tendremos que cambiar las siguientes líneas:

mySignal = QtCore.pyqtSignal(int)
...
self.mySignal.emit(self.i)
...
def myTooMuch(v):
    print 'Too Much: ' + str(v)

Creación de GUIs

Layouts

Los Layout ayudan a organizar la distribución de los constroles (widgets) en una ventana. Para utilizarlos en Qt simplemente has de agregarlos a la ventana y a este los widgets mediante el método addWidget:

class MyWindow (QtGui.QWidget):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.layout1 = QtGui.QVBoxLayout(self)
        self.button1 = QtGui.QPushButton("Click Me")
        self.button2 = QtGui.QPushButton("Click Me")
        self.layout1.addWidget(self.button1)
        self.layout1.addWidget(self.button2)

Existen varios métodos de layout:

  • QVBoxLayout: Donde los elementos se muestran en vertical.
  • QHBoxLayout: Donde los elementos se muestran en horizontal.
  • QGridLayout

GUIs con el Qt4 Designer

El Qt4 Designer es una herramienta que puedes instalar y que te permite crear GUIs de forma rápida e intuitiva. Como Qt es un framework ideado para C\C++ el archivo resultado, con extensión .ui, tendrá que ser pasado a Python, para ello utilizaremos el comando pyuic4:

pyuic4 untitled.ui -o window.py

Una vez tengamos el archivo .py lo colocaremos en la misma carpeta y haremos un import de la clase resultado, según el tipo que hayamos creado podremos tratarla de varias formas:

from window import Ui_Form
class MyWindow (QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.gui = Ui_Form()
        self.gui.setupUi(self)
        self.gui.pushButton.clicked.connect(self.btnClick)
 
    def btnClick (self):
        print "a"

Qt Style Sheets

self.setStyleSheet("QWidget { background-color: rgb(255, 255, 255); background-image: url(heart.png); border-top:5px solid rgb(255, 170, 255); }")

Clases básicas

  • QGui.QDesktopWidget: Permite el acceso a información del escritorio (número de pantallas, resolución…).

Clases de Widgets

Creación avanzada de aplicaciones

Paint & QImages

Pintar sobre QWidgets

Para poder pintar sobre un QWidget lo haremos sobreescribiendo el método paintEvent de este y mediante los métodos de un objeto QPainter, lo crearemos y luego, entre sus los métodos begin (al cual le tendremos que pasar el QWidget sobre el cual pintaremos) y end llevaremos a cabo los métodos de pintar:

class MyWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
 
    def paintEvent(self, event):
        paint = QtGui.QPainter()
        paint.begin(self)
 
        paint.setPen(QtGui.QColor(168, 34, 3))
        paint.setFont(QtGui.QFont('Verdana', 23))
        paint.drawText(event.rect(), QtCore.Qt.AlignCenter, "Pintooo!")
        paint.drawRect(100, 100, 200, 200)
        paint.fillRect(150, 150, 199, 199, QtGui.QColor(255,0,0))
        paint.drawImage(QtCore.QRect(0,0, 80, 80), QtGui.QImage("heart.png"))        
 
        paint.end()

El método repaint() de un QWidget hará que se vuelva a llamar al método paintEvent.

La clase QImage

Pintar sobre QImage

También podemos pintar sobre una QImage con el QPainter:

    def paintEvent(self, event):
        i = QtGui.QImage(event.rect().width(), event.rect().height(), QtGui.QImage.Format_ARGB32)
        ipaint = QtGui.QPainter()
        ipaint.begin(i)
        ipaint.drawImage(event.rect(), QtGui.QImage("heart.png"))
        ipaint.end()
 
        paint = QtGui.QPainter()
        paint.begin(self)        
        paint.drawImage(event.rect(), i);
        paint.end()

Notas sobre imágenes

  • Podemos mostrar imágenes a partir de QLabels asignando su propiedad PixMap:
self.lbl = QtGui.QLabel(self)
qPixMap = QtGui.QPixmap.fromImage(QtGui.QImage("heart.png"))
self.lbl.setPixmap(qPixMap)
fw/pyqt4.1278184022.txt.gz · Última modificación: 2020/05/09 09:24 (editor externo)