Cómo desarrollar aplicaciones en QT con Python 3

Una de las ventajas de programar en Python es que es un lenguaje que puede correr en cualquier sistema operativo moderno, por lo que se hace indispensable poder asociarlo con un framework que tambien sea multiplataforma. Uno de los frameworks mas populares es QT, y su ‘binding’ oficial pyside2. Vamos a ver un par de ejemplos, pero antes de esto asegurate de tener instalado Python 3, Qt Framework y Qt Creator. Despues instalas pyside2, pero primero debes actualizar la version de pip.

python3 -m pip install --upgrade pip
pip install PySide2

En este par de ejemplos, seguiremos con el mismo ejemplo de entradas anteriores: el juego “Preguntale a la Bola 8”. Primero generamos el archivo .ui en Qt Creator, vamos a nombrarlo “mainwindow.ui”.

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Eight Ball Answer</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout_2">
    <item>
     <layout class="QVBoxLayout" name="verticalLayout">
      <item>
       <widget class="QTextEdit" name="txtQuestion">
        <property name="font">
         <font>
          <pointsize>24</pointsize>
         </font>
        </property>
        <property name="html">
         <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:24pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:160%; background-color:#f5f5f5;&quot;&gt;&lt;span style=&quot; font-family:'Monaco','Consolas','Andale Mono','DejaVu Sans Mono','monospace'; color:#383838;&quot;&gt;[Place question here.]&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QPushButton" name="button">
        <property name="text">
         <string>Ask the 8 Ball</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QTextEdit" name="txtAnswer">
        <property name="font">
         <font>
          <pointsize>24</pointsize>
         </font>
        </property>
        <property name="html">
         <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:24pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:160%; background-color:#f5f5f5;&quot;&gt;&lt;span style=&quot; font-family:'Monaco','Consolas','Andale Mono','DejaVu Sans Mono','monospace'; color:#383838;&quot;&gt;[Answer will appear here.]&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
        </property>
       </widget>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

Despues vamos a usar pyside2-uic para convertir el archivo .ui a codigo Python. En este archivo “mainwindow.py” estara la clase base de la interface grafica:

pyside2-uic mainwindow.ui > ui_mainwindow.py

Ahora vamos a teclear la llamada a la clase base y la funcion principal. Nombraremos a este archivo “EightBall.qt-uic.py”:

import sys
from PySide2.QtWidgets import QApplication, QMainWindow
from PySide2.QtCore import QFile, Qt
from mainwindow import Ui_MainWindow
import random
from time import sleep

class AnswerGenerator():
    answers = ["Ask Again later"
    , "Can Not Predict Now","Without a Doubt"
    , "Is Decidely So","Concentrate and Ask Again","My Sources Say No"
    , "Yes, Definitely","Don't Count On It","Signs Point to Yes"
    , "Better Not Tell You Now","Outlook Not So Good","Most Likely"
    , "Very Doubtful","As I See It, Yes","My Reply is No","It Is Certain"
    , "Yes","You May Rely On It","Outlook Good","Reply Hazy Try Again"]
    
    def get_random_answer(self):
        return self.answers[random.randrange(0, len(self.answers))]

class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)
        self.connect_signals_to_slots()
        self.show()

    def connect_signals_to_slots(self):
        self.button.clicked.connect(self.cmdAnswer_Click)

    # Slots
    def cmdAnswer_Click(self):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        sleep(2)
        generator = AnswerGenerator()
        self.txtAnswer.setText(generator.get_random_answer())
        QApplication.restoreOverrideCursor()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())

Ejecuta el programa: python3 EightBall.qt-uic.py

La otra manera de trabajar la interfaz grafica, es trabajando el archivo .ui sin tener que convertirlo a codigo Python, no sé si por costumbre, pero esta opcion no es mi preferida, aunque convertir implique un paso extra. Este metodo tiene la ventaja que puedes modificar la GUI y probar los cambios inmediatamente despues de grabar. A pesar de mis prejuicios contra esta alternativa, tambien la vamos a probar.

Antes que nada asegurate de grabar el siguiente archivo en la misma ruta que “mainwindow.ui”. Desde este programa cargaremos el .ui a la clase final y alojaremos la funcion principal, nombralo “EightBall.qt-ui.py”:

import sys
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import QApplication
from PySide2.QtCore import QFile, QObject, Qt
import random
from time import sleep

class AnswerGenerator():
    answers = ["Ask Again later"
    , "Can Not Predict Now","Without a Doubt"
    , "Is Decidely So","Concentrate and Ask Again","My Sources Say No"
    , "Yes, Definitely","Don't Count On It","Signs Point to Yes"
    , "Better Not Tell You Now","Outlook Not So Good","Most Likely"
    , "Very Doubtful","As I See It, Yes","My Reply is No","It Is Certain"
    , "Yes","You May Rely On It","Outlook Good","Reply Hazy Try Again"]
    
    def get_random_answer(self):
        return self.answers[random.randrange(0, len(self.answers))]

class MainWindow(QObject):
    def __init__(self, ui_filename):
        super(MainWindow, self).__init__()
        ui_file = QFile(ui_filename)
        ui_file.open(QFile.ReadOnly)
        loader = QUiLoader()
        self.ui = loader.load(ui_file)
        ui_file.close()
        self.connect_signals_to_slots()
        self.ui.show()

    def connect_signals_to_slots(self):
        self.ui.button.clicked.connect(self.cmdAnswer_Click)

    # Slots
    def cmdAnswer_Click(self):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        sleep(2)
        generator = AnswerGenerator()
        self.ui.txtAnswer.setText(generator.get_random_answer())
        QApplication.restoreOverrideCursor()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow('mainwindow.ui')
    sys.exit(app.exec_())

Es importante que notes que solo cambiamos la importacion de algunos modulos, el dunder __init__, y la linea de codigo donde creamos la clase MainWindow('mainwindow.ui'), donde pasamos como parametro el nombre del archivo .ui. El resto del codigo permanece intacto.

En una publicacion proxima haremos este mismo ejercicio con GTK3, mientras tanto, espero que este par de ejercicios te sean utiles para empesar a programar tus interfaces graficas en Qt con Python 3, usando pyside2.

Tienes alguna duda? Sugerencias? Pues deja tu comentario.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s