PyQt 07 – QLabel e Qt Designer

Este artigo é a parte 7 de 14 na série PyQt

Deste artigo em diante, apresentarei diferentes Widgets da Qt, iniciando por Widgets básicas como a QLabel, QLineEdit, QpushButton, entre outras. Para deixar o trabalho mais fluido e não ter que me preocupar com a construção e modelagem das janelas de diálogos, vou aproveitar e fazer uma breve introdução do aplicativo Designer, um construtor de GUI (Graphical User Interface) bem simples, oferecida juntamente com a biblioteca Qt.

Não é intenção deste texto ser um tutorial do uso do Qt Designer, ainda porque existem muitos outros artigos na rede que se propõem a isto. O foco aqui será mais no desenvolvimento do aplicativo, como as conexões dos sinais e o uso de alguns métodos e atributos interessantes para este desenvolvimento.

Widget QLabel

A widget QLabel permite apresentar um texto ou uma imagem. Para se familiarizar com as widgets do Qt é interessante sempre verificar a árvore de herança da classe apresentada. Isto deve acrescentar no momento de determinar os métodos, atributos e sinais relevantes em uma classe, bem como os herdados. A árvore de herança da classe QLabel é apresentada a seguir:

QLabel -> QFrame -> QWidget -> QObject  
                               QPaintDevice

Criar o costume de conhecer as classes herdadas pelos widgets, irá render um conhecimento mais consistente do toolkit Qt, essencial para desenvolver um bom aplicativo.

Para prosseguir com a investigação do QLabel, crie um diálogo simples com apenas dois labels como no código abaixo:

#!/bin/env python                 
#                                 
# Hello World por Rudson R. Alves
#

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class MyDialog(QDialog):
  def __init__(self, parent = None):
    super(MyDialog, self).__init__(parent)

    label1 = QLabel("<h2>Hello</h2>")
    label2 = QLabel("<h1 style=\"color: #0000FF\">World...</h1>")

    vbox = QVBoxLayout()
    vbox.addWidget(label1)
    vbox.addWidget(label2)

    self.setLayout(vbox)

app = QApplication(sys.argv)
dlg = MyDialog()
dlg.exec_()

Este código deve gerar o diálogo abaixo:

A widget QLabel aceita como entrada uma string simples, rick text, tags html e uma QString (string com caracteres unicode).

Sinais emitidos pela QLabel

A widget QLabel emite apenas dois sinais:

[TABLE=22]

O código abaixo mostra os dois sinais em ação:

#!/bin/env python                       
# -*- coding: iso-8859-1 -*-            
#                                       
# qlable_url por Rudson R. Alves       
#                                       

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import * 

class MyDialog(QDialog):

  def __init__(self, parent = None):
    super(MyDialog, self).__init__(parent)
    self.link_label = QLabel("Passe o mouse sobre o link: QLabel")       
    self.msg_label = QLabel("")                                                 

    vbox = QVBoxLayout()
    vbox.addWidget(self.link_label)
    vbox.addWidget(self.msg_label)

    self.connect(self.link_label, SIGNAL("linkActivated(QString)"), self.Activated)
    self.connect(self.link_label, SIGNAL("linkHovered(QString)"), self.Hovered)

    self.setLayout(vbox)

  def Activated(self, url):
    print "linkActivated..."
    QDesktopServices().openUrl(QUrl(url))

  def Hovered(self, url):
    print "linkHovered..."
    if self.msg_label.text() == "":
      self.msg_label.setText("Click no link para abrir no browser.\nClick com o botão direito para copiar o link.")
    else:
      self.msg_label.setText("")

app = QApplication(sys.argv)
dlg = MyDialog()
dlg.exec_()

Este código vai gera um diálogo simples com uma mensagem. A segunda mensagem aparecerá ao passar o mouse sobre o link QLabel. Clicando sobre o link o browser padrão de seu sistema deve abrir com a página da documentação completa do QLabel, direto da página oficial do PyQt.

A mágica é feita nas linhas 22 e 23, onde os sinais emitidos pelo QLabel link_label são conectados aos slots (neste caso métodos da classe MyDialog) Activated e Hovered. A conexão é feita pelo comando connect seguindo a sintaxe:

self.connect(Objeto, SIGNAL("Sinal emitido pelo Objeto"), Slot a ser conectado)

O Slot a ser conectado pode ser tanto um método de um dos objetos de sua janela (geralmente chamado de slot), ou um método criado em sua classe.

O sinal emitido pelos objetos podem ser conhecido investigando a documentação do PyQt. Basta pesquisar a classe desejada e verificar os seus sinais emitidos. Em alguns casos, o sinal desejado pode estar em alguma das classes herdadas, por isto não deixe de ver suas heranças.

Designer

O aplicativo Qt Designer é distribuído juntamente com a toolkit Qt, sobre o nome designer. Ele é um poderoso editor de interface gráfica para usuário, no entanto trabalha apenas com a biblioteca Qt.

Em um terminal, execute o comando designer para abri o construtor de GUI. A tela inicial é semelhante a apresentada a seguir:

Para este primeiro contado, vou construir o mesmo diálogo anterior. Para isto selecione um diálogo sem botões (Dialog without buttons). Isto deve criar um diálogo vazio.

Primeiro altere o nome do diálogo, editando o campo ObjectName, na caixa de Propriedades (Property) no centro à esquerda, como mostra a figura a seguir:

Agora altere o título que aparece na parte superior do diálogo, editando o campo windowTitle,

.

Para terminar o diálogo, falta adicionar os dois QLabels: link_label e msg_label, como feito no código anterior. Para isto, role a barra de rolagem da caixa Widget Box, à esquerda do Designer, até aparecer a seção Display Widgets. Logo no início desta seção você vai encontrar a widget QLabel, com o nome Label.

Agarre a widget QLabel na Widget Box e a solte sobre o diálogo. Repita o processo para a segunda QLabel. Seu diálogo deve ficar com a aparência abaixo:

Em seguida de um duplo click sobre o primeiro QLabel para alterar o seu texto, ou edite a propriedade text, com o texto “Passe o mouse sobre o link: <a href=\”http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qlabel.html\”>QLabel</a></em>”.

Repita o processo para o segundo QLabel, com o texto: “Click no link para abrir no browser.\nClick com o botão direito para copiar o link.”

Para terminar, resta ainda aplicar o Layout Vertical. Clique sobre o diálogo (atenção para não selecionar nenhum dos QLabels) e em seguida clique no botão Lay Out Vertically, circulado em verde na figura abaixo:

Isto irá deixar o diálogo com a aparência abaixo:

Selecione o primeiro QLabel para altera o seu nome (propriedade objectName) para link_label e o segundo QLabel para msg_label.

Agora o diálogo está pronto. Salve-o com o nome “link_qlabel.ui“. O Python não consegue trabalhar diretamente com este arquivo UI. É necessário criar um módulo a partir deste arquivo com o comando pyuic4.

 
pyuic4 -o link_qlabel.py link_qlabel.ui

Isto irá gerar um módulo link_qlabel.py com a classe Ui_QLabel_url_Dialog, com dois métodos: setupUi e retranslateUi. Agora crie o código para o novo aplicativo com o conteúdo a seguir:

#!/bin/env python
# -*- coding: iso-8859-1 -*-
#
# Hello World por Rudson R. Alves
#

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from link_qlabel import *

class MyDialog(QDialog, Ui_QLabel_url_Dialog):

  def __init__(self, parent = None):
    super(MyDialog, self).__init__(parent)
    self.setupUi(self)

app = QApplication(sys.argv)
dlg = MyDialog()
dlg.exec_()

Este código apenas permite abrir o diálogo, mas ainda não tem nenhuma funcionalidade. Em seguida adicione as conexões aos sinais como no código anterior.

#!/bin/env python                                                     
# -*- coding: iso-8859-1 -*-                                          
#                                                                     
# Hello World por Rudson R. Alves                                     
#                                                                     

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import * 
from link_qlabel import * 

class MyDialog(QDialog, Ui_QLabel_url_Dialog):

  def __init__(self, parent = None):
    super(MyDialog, self).__init__(parent)
    self.setupUi(self)

    self.connect(self.link_label, SIGNAL("linkActivated(QString)"), self.Activated)
    self.connect(self.link_label, SIGNAL("linkHovered(QString)"), self.Hovered)

  def Activated(self, url):
    print "linkActivated..."
    QDesktopServices().openUrl(QUrl(url))

  def Hovered(self, url):
    print "linkHovered..."
    if self.msg_label.text() == "":
      self.msg_label.setText("Click no link para abrir no browser.\nClick com o botão direito para copiar o link.")
    else:
      self.msg_label.setText("")

app = QApplication(sys.argv)
dlg = MyDialog()
dlg.exec_()

O uso do Qt Designer deixa o seu código bem mais limpo, uma vez que não há a necessidade de criar todos os elementos do diálogo, como os labels, vbox, … Mas as habilidades do Qt Designer vai bem além de apenas simplificar o trabalho na criação das janelas. Explorar tudo é algo extenso e nem mesmo acredito que saiba tando assim para apresentar.

Uma destas habilidades que gosto muito de utilizar é a conexão de sinais automática, que despolui muito o código. Mas antes de uma olhada na classe Ui_QLabel_url_Dialog, criada pelo pyuic4 ao processar o arquivo ui gerado pelo Qt Designer:

class Ui_QLabel_url_Dialog(object):
    def setupUi(self, QLabel_url_Dialog):
        QLabel_url_Dialog.setObjectName("QLabel_url_Dialog")
        QLabel_url_Dialog.resize(335, 99)                   
        self.verticalLayout = QtGui.QVBoxLayout(QLabel_url_Dialog)
        self.verticalLayout.setObjectName("verticalLayout")
        self.link_label = QtGui.QLabel(QLabel_url_Dialog)
        self.link_label.setObjectName("link_label")
        self.verticalLayout.addWidget(self.link_label)
        self.msg_label = QtGui.QLabel(QLabel_url_Dialog)
        self.msg_label.setObjectName("msg_label")
        self.verticalLayout.addWidget(self.msg_label)

        self.retranslateUi(QLabel_url_Dialog)
        QtCore.QMetaObject.connectSlotsByName(QLabel_url_Dialog)

    def retranslateUi(self, QLabel_url_Dialog):
        QLabel_url_Dialog.setWindowTitle(QtGui.QApplication.translate("QLabel_url_Dialog", "QLabel Links Signals", None, QtGui.QApplication.UnicodeUTF8))
        self.link_label.setText(QtGui.QApplication.translate("QLabel_url_Dialog", "Passe o mouse sobre o link: QLabel", None, QtGui.QApplication.UnicodeUTF8))
        self.msg_label.setText(QtGui.QApplication.translate("QLabel_url_Dialog", "Click no link para abrir no browser.\nClick com o botão direito para copiar o link.", None, QtGui.QApplication.UnicodeUTF8))

Como pode ser visto, o método setupUi é quem cria os elementos do diálogo, alinhando-os e atribuindo-lhe as informações editadas no Qt Designer. O método retranslateUi translada o texto para UTF-8 e preenche as QLabels com os textos padrões. Mas quem faz a mágica a que estou interessado em discutir aqui é o método connectSlotsByName, da classe QMetaObject, chamado na linha 15 da classe acima.

Este método pesquisa recursivamente os objetos e objetos filhos, conectando os sinais aos slots que possuem a seguinte forma:

@pyqtSignature("")
def on__();

O decorador “@pyqtSignature” não é obrigatório, mas garante que o sinal capturado será sempre o desejado. Ele deve passar a assinatura do sinal a ser capturado. Isto pode ser conhecido consultando o sinal da widget desejada, neste caso os sinais do QLabel. Estes sinais foram apresentados acima, e suas assinaturas são idênticas, retornando sempre uma QString.

Fazendo mais algumas mudanças ao código, substituindo as conexões e redefinindo os métodos Activated e Hovered para serem conectados automaticamente pelo connectSlotsByName, o código pode ficar ainda mais simples:

#!/bin/env python                                                               
# -*- coding: iso-8859-1 -*-                                                    
#                                                                               
# Hello World por Rudson R. Alves                                               
#                                                                               

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import * 
from link_qlabel import * 

class MyDialog(QDialog, Ui_QLabel_url_Dialog):

  def __init__(self, parent = None):
    super(MyDialog, self).__init__(parent)
    self.setupUi(self)

  @pyqtSignature("QString")
  def on_link_label_linkActivated(self, url):
    print "linkActivated %s" % url
    QDesktopServices().openUrl(QUrl(url))

  @pyqtSignature("QString")
  def on_link_label_linkHovered(self, url):
    print "linkHovered %s" % url
    if self.msg_label.text() == "":
      self.msg_label.setText("Click no link para abrir no browser.\nClick com o botão direito para copiar o link.")
    else:
      self.msg_label.setText("")

app = QApplication(sys.argv)
dlg = MyDialog()
dlg.exec_()

Além da uma mensagem, a url agora será impressa a cada sinal emitido pelo QLabel link_label.

Os códigos desenvolvidos neste texto podem ser baixados pelo link: pyqt-07.zip.

Bom até o próximo…

Este post tem um comentário

  1. Rodrigo

    Parabéns pela série de posts sobre PyqT, ESTÃO EXCELENTES!

    Muito Obrigado, estou aprendendo muito!

    Um abraço!

Deixe um comentário

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.