[TUTORIAL] Python e Qt 5 [Parte 2]

tutorial
python
#1

Desta parte 2 vamos ver como criar interfaces utilizando o Qt Designe e o Qt Creator. Em seguida vamos ver como ler/manipular o arquivo *.ui gerado por essas ferramentas.

A ideia é criar uma interface com o mesmo designe e funcionalidades que fizemos no GTK+ 3, basicamente vamos seguir o seguinte modelo:

builder-app-running

Como foi dito na parte 1 é comum vermos tutoriais onde o designe da interface é feito diretamente no código Python, um exemplo desta forma de criar a interface seria:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Python e PyQt5.

Criando a interface no Python.
"""
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QLineEdit, QLabel,
                             QPushButton, QApplication)


class MeuAplicativo(QWidget):
    """Classe"""

    def __init__(self):
        """Construtor."""
        super().__init__()
        # Janela principal.
        self.setWindowTitle('Olá Mundo')
        self.setObjectName('Widget')
        self.resize(400, 300)

        # Gerenciador de layout.
        verticalLayout = QVBoxLayout()
        verticalLayout.setObjectName('verticalLayout')
        self.setLayout(verticalLayout)

        # Widgets.
        self.lineEdit = QLineEdit()
        self.lineEdit.setObjectName('lineEdit')
        self.lineEdit.setPlaceholderText('Digite algo')
        verticalLayout.addWidget(self.lineEdit)

        self.label = QLabel()
        self.label.setObjectName('label')
        self.label.setText('Este texto será alterado!')
        self.label.setAlignment(Qt.AlignCenter)
        verticalLayout.addWidget(self.label)

        self.pushButton = QPushButton()
        self.pushButton.setObjectName('pushButton')
        self.pushButton.setText('Clique Aqui')
        self.pushButton.clicked.connect(self._on_button_clicked)
        verticalLayout.addWidget(self.pushButton)

    def _on_button_clicked(self):
        """Método é executado quando o botão é pressionado."""
        # Coletando o valor do campo de entrada de texto.
        text = self.lineEdit.text()
        # Verificando se algo foi digitado.
        if text:
            self.label.setText(text)
        else:
            self.label.setText('Digite algo no campo de texto :)')


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    ui = MeuAplicativo()
    ui.show()
    sys.exit(app.exec_())

python-designe-code

Essa é uma forma totalmente válida de se desenvolver um aplicativo, todavia temos como limitação o fato de não poder separar a lógica da parte visual, além de limitar a possibilidade de se trabalhar com uma equipe para o designe e uma para a lógica.

Agora vamos ver uma outra possibilidade para o código a cima. Desta vez separando o designer da parte lógica.

Qt Designer

Se você optar por utilizar o Qt Designer, basta executar ele que o mesmo irá solicitar o tipo de janela que se deseja criar:

Eu escolhi o tipo Widget por que não será um interface que utiliza menus e area de status.

Assim como no Gnome Glade, tente desenhar a interface até chegar em um resultado próximo a:

qt-designer-widget-preview

Para visualizar o resultado do que está sendo criado basta utilizar o atalho Ctrl + r.

Importante notar que os widgets criados tem um campo chamado objectName este campo deve ser único, visto que iremos acessar os widgets por este nome:

Caso não queira desenhar a interface crie um arquivo chamado mainwindow-designer.ui e cole o seguinte código XML:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Olá Mundo</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <widget class="QLineEdit" name="lineEdit">
     <property name="inputMask">
      <string/>
     </property>
     <property name="text">
      <string/>
     </property>
     <property name="placeholderText">
      <string>Digite algo</string>
     </property>
    </widget>
   </item>
   <item>
    <widget class="QLabel" name="label">
     <property name="text">
      <string>Este texto será alterado!</string>
     </property>
     <property name="alignment">
      <set>Qt::AlignCenter</set>
     </property>
    </widget>
   </item>
   <item>
    <widget class="QPushButton" name="pushButton">
     <property name="text">
      <string>Clique Aqui</string>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

Qt Creator

Já com o Qt Creator vamos precisar criar um novo projeto, para isso vamos no menu superior e clicamos em file &gt; New File or Project, na janela que se abre vamos escolher Application e Qt Widgets Applicativon:

Na tela seguinte podemos definir o nome do projeto e o local dele. clique em Next:

Agora temos a tela onde definimos o kit. Caso seja necessário crie um. clique em Next:

Na tela que segue podemos definir informações sobre a class (classe), contudo isso não é importante, visto que não vamos utilizar C/C++, apenas clique em Next:

Por fim temos a ultima tela. clique em Finish:

Com o projeto criado clique sobre a pasta forms e clique no arquivo mainwindow.ui, com isso o modo de designe será aberto:

Agora basta criar a interface, como fizemos com o Qt Designer:

Caso você queira visualizar o resultado enquanto cria a interface basta utilizar o atalho Ctrl + r.

> OBS: Vale notar que o Qt Creator gera uma janela do tipo MainWindow, contudo isso não é um problema, uma vez que nossos widgets terão o mesmo objectName.

Caso não queira tentar desenhar a interface crie um arquivo chamado mainwindow-creator.ui e cole o seguinte código XML:

<?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>Olá Mundo</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QLineEdit" name="lineEdit">
      <property name="placeholderText">
       <string>Digite algo</string>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QLabel" name="label">
      <property name="text">
       <string>Este texto será alterado!</string>
      </property>
      <property name="alignment">
       <set>Qt::AlignCenter</set>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QPushButton" name="pushButton">
      <property name="text">
       <string>Clique Aqui</string>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menuBar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>400</width>
     <height>22</height>
    </rect>
   </property>
  </widget>
  <widget class="QToolBar" name="mainToolBar">
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

Interfaces criadas, agora podemos avançar para o código em Python.

Python

> OBS: Eu realmente recomendo que você crie um ambiente virtual e instale as depêndencias neste ambiente, contudo não é obrigatorio é apenas uma recomendação.

Vamos começar criando a pasta do projeto, eu criei um pasta com o nome ola-mundo, sinta-se avontade para criar uma pasta com o nome que preferir.

Essa pasta terá a seguinte estrutura:

ola-mundo
├── forms
│   ├── mainwindow-creator.ui
│   └── mainwindow-designer.ui
├── icons
│   ├── icon.ico
│   └── icon.png
├── MainWindow.py
└── Pipfile

Estrutura do projeto

> OBS: O arquivo Pipfile é porque eu estou utilizando o pipenv para gestão do meu ambiente virtual. Se você não utilizar o pipenv este arquivo não irá existir e não é necessário.

> OBS: Tenho 2 aquivos de interface dentro da pasta forms porque criei uma interface com o Qt Creator e outra com o Qt Designe.

Agora que temos um estrutura básica do projeto vamos instalar o PyQt5, se você estiver utilizando um ambiente virtual (lembre-se de ativar o ambiente!):

pip install pyqt5

Se estiver instalando diretamente no Python do S.O.:

sudo pip3 install pyqt5

> OBS: Caso você tenha mais de uma versão do Python 3 no sistema lembre-se de verificar em qual a instalação está sendo feita ou utilize: python3.x -m pip install pyqt5. Substitua o x pela versão de Python que deseja.

Com o PyQt5 instalado vamos abrir/criar o arquivo MainWindow.py e digitar o seguinte código:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Python e PyQt5.

Acessando/interagindo com um arquivo ``*.ui`` (XML).
"""
from PyQt5.QtWidgets import QApplication
from PyQt5.uic import loadUi


class MeuAplicativo:
    """Classe."""

    def __init__(self, window):
        """Construtor."""
        # Widgets
        self.label = window.label
        self.line_edit = window.lineEdit
        self.push_button = window.pushButton
        # Conectando um método ao evento de clique do botão.
        self.push_button.clicked.connect(self._on_button_clicked)

    def _on_button_clicked(self):
        """Método é executado quando o botão é pressionado."""
        # Coletando o valor do campo de entrada de texto.
        text = self.line_edit.text()
        # Verificando se algo foi digitado.
        if text:
            self.label.setText(text)
        else:
            self.label.setText('Digite algo no campo de texto :)')


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    # Lendo o arquivo de interface.
    # window = loadUi('forms/mainwindow-creator.ui')
    window = loadUi('forms/mainwindow-designer.ui')
    ui = MeuAplicativo(window=window)
    window.show()
    sys.exit(app.exec_())

Ao executar o código a cima temos:

python-designe-code

Nossa interface criada no Qt Designer ou Qt Creator integrada no Python.

O que vejo como principal beneficio deste método é que temos uma boa separação da logica de programação do desginer da interface, favorecendo inclusive o trabalho onde podemos ter um time cuidado da interface e outro da lógica.

Bom com isso temos um pequena introdução a criação de interfaces gráficas com Python e Qt 5. Talvez haja uma parte 3 com alguns código de exemplo para o PySide2 ou algo assim :smiley: .

E claro se encontrar algum erro ou dificuldade entre em contato para que o material possa ser atualizado.

3 Likes

[TUTORIAL] Python e Qt 5 [Parte 3]
#2

Esse tipo de postagem é bom demais…
é isso que precisamos aqui

2 Likes

#3

Como faz com gtk? Tô aprendendo python aos pouquinhos

1 Like

#4

Muito interessante e completo o Tutorial!! Parabéns @natorsc !!

@filipemosca tem um tutorial completo sobre PyGTK em português aqui:
https://python-gtk-3-tutorial.readthedocs.io/pt_BR/latest/

Eu estou aprendendo Vala-GTK e de vez em quando vou na documentação do python pra esclarecer as coisas, já que documentação de Vala é escarsa.

2 Likes