¡Esta es una revisión vieja del documento!
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:
Y también algunas utilidades como:
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.
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_())
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:
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.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_())
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)
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:
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"
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.
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()
PixMap:self.lbl = QtGui.QLabel(self) qPixMap = QtGui.QPixmap.fromImage(QtGui.QImage("heart.png")) self.lbl.setPixmap(qPixMap)
self.setStyleSheet("QWidget { background-color: rgb(255, 255, 255); background-image: url(heart.png); border-top:5px solid rgb(255, 170, 255); }")