PyQt 12 – QComboBox

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

O QComboBox é uma widget muito versátil que combina uma lista e um botão de forma bem compacta. O elemento selecionado é sempre apresentado, podendo ser ele tanto uma string como um pixmap.

Neste texto vou apresentar a carga, seleção, edição, bem como outras habilidades interessantes da widget QComboBox.

Neste texto vou construir um diálogo hipotético para um simples cadastro de vendedores, onde vendedores naturais de um estado são designados a operarem em uma região (falta de imaginação não…). O diálogo é apresentado na figura abaixo:

O código e diálogo usado neste texto pode ser baixado no link: pyqt-12.zip

O seu código foi gerado no Qt Designer, conectando os botões Ok e Cancelar aos sinais accept() e reject() do diálogo. O código a seguir servirá de base para o desenvolvimento deste diálogo:

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

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

class ComboBoxDialog(QDialog, Ui_Dialog):
    def __init__(self, nome = None, parent = None):
        super(ComboBoxDialog, self).__init__(parent)
        self.setupUi(self)

        if nome:
            self.lineEdit_vendedor.setText(nome)

        estados = [u'Acre', u'Alagoas', u'Amapá', u'Amazonas', \
                   u'Bahia', u'Ceará', u'Distrito Federal', \
                   u'Espírito Santo', u'Goiás', u'Maranhão', \
                   u'Mato Grosso', u'Mato Grosso do Sul', \
                   u'Minas Gerais', u'Pará', u'Paraíba', u'Paraná', \
                   u'Pernambuco', u'Piauí', u'Rio de Janeiro', \
                   u'Rio Grande do Norte', u'Rio Grande do Sul', \
                   u'Rondônia', u'Roraima', u'Santa Catarina',
                   u'São Paulo', u'Sergipe', u'Tocantins']

        self.comboBox_estado.addItems(estados)


    def accept(self):
        print u'\nSaída'
        print u'Estado: %s' % self.comboBox_estado.currentText()
        print u'Índice: %d' % self.comboBox_estado.currentIndex()
        print u'Região: %s' % self.comboBox_regiao.currentText()
        print u'Índice: %d' % self.comboBox_regiao.currentIndex()
        QDialog.accept(self)

app = QApplication(sys.argv)
dlg = ComboBoxDialog(u'Alberto Roberto')
dlg.exec_()

O QComboBox região foi preenchido durante a construção do diálogo no Qt Designer, no entanto, o QComboBox dos estados é preenchido com os estados contidos na lista estados, definida na linha 20. O preenchimento é feito com o método addItems, na linha 30, que recebe como argumento uma lista de strings, ou mais precisamente, uma QStringList.

Outro método que poderia fazer o mesmo é o addItem, com o auxílio de um loop. O addItem ainda comporta a entrada de objetos QIcon, para criar listas de icones no ComboBox.

A função accept(self), declarada na linha 33, redefine a saída padrão do diálogo, imprimido os conteúdos das seleções dos diálogos, índice e conteúdo. Isto é uma redefinição do método padrão accept, herdada da classe QDialog, que termina por ser invocada na linha 39.

Sinais

Como de praxe, apresento a seguir os sinais suportados pela classe QComboBox.

[TABLE=31]

Observe que os sinais currentIndexChanged(int) e currentIndexChanged(QString), são o mesmo sinal. Não é possível capiturar ambos simultaneamente. Um código como o seguinte:

    @pyqtSignature("QString")
    def on_comboBox_regiao_currentIndexChanged(self, text):
        print u'Região texto alterado: %s' % text

    @pyqtSignature("int")
    def on_comboBox_regiao_currentIndexChanged(self, index):
        print u'Região índice alterado: %s' % index

retornará apenas o índice do elemento selecionado, uma vez que a definição na linha 46 será compreendida pelo Python como uma redefinição do método on_comboBox_regiao_currentIndexChanged.

O mesmo acontece com o par de sinais activated(int) e activated(QString), e o par highlighted(int) e highlighted(QString).

Implementando Sinais

Inicialmente vou implementar os sinais currentIndexChanged(QString), dos dois ComboBox, fazendo com que uma mensagem seja impressa, mostrando a string selecionada. Isto é feito adicionando as linhas abaixo, a partir da linha 33 do código original:

    @pyqtSignature("QString")
    def on_comboBox_estado_currentIndexChanged(self, text):
        print u'Estado texto alterado: %s' % text


    @pyqtSignature("QString")
    def on_comboBox_regiao_currentIndexChanged(self, text):
        print u'Região texto alterado: %s' % text

Ao selecionar os diferentes elementos dos ComboBox região e estado, seus conteúdos serão impressos, gerando uma saída semelhante à abaixo, no console:

./dialog_vendedor
Estado texto alterado: Acre
Estado texto alterado: Alagoas
Estado texto alterado: Amapá
Estado texto alterado: Amazonas
Estado texto alterado: Bahia
Região texto alterado: Sul
Região texto alterado: Nordeste
Região texto alterado: Sudeste

Saída
Estado: Bahia
Índice: 4
Região: Sudeste
Índice: 3

Neste teste naveguei com o TAB, pelos elementos do diálogo, selecionando o estado e depois a região com as teclas direcionais. As últimas 5 linhas são impressas após pressionar o botão Ok do diálogo, ou a tecla ENTER.

Na próxima implementação, adiciono o sinal activated ao ComboBox estado apenas. As linhas abaixo fazem a implementação:

    @pyqtSignature("QString")
    def on_comboBox_estado_activated(self, text):
        print u'Estado texto activated: %s' % text

Como explicado na tabela de sinais acima, esta sinal será emitido sempre que um estado for selecionado. Aparentemente isto parece replicar o sinal currentIndexChanged, no entanto, esta sinal será emitido mesmo que o mesmo estado seja selecionado novamente. Experimente executar o código e fazer o seguinte procedimento:

  • Pressione TAB para mudar para o ComboBox estado;
  • em seguida pressione a letra ‘G‘. Isto irá selecionar o estado de ‘Goiás‘, o primeiro com a letra ‘G‘;
  • em seguida, usando o mouse, pressione no ComboBox estado e selecione novamente o estado de Goiás

observe que isto irá emitir um novo sinal activated, mas não o currentIndexChanged, uma vez que o texto não foi alterado. Veja a saída no console, abaixo:

./dialog_vendedor
Estado texto alterado: Acre
Estado texto alterado: Goiás
Estado texto activated: Goiás
Estado texto activated: Goiás

Nas próximas linhas adiciono o código para habilitar a edição no ComboBox região. Para isto será necessário usar o CheckBox região, para mudar o estado Editable do ComboBox. As linhas a seguir fazem isto:

    @pyqtSignature("int")
    def on_checkBox_regiao_stateChanged(self, status):
        if status == Qt.Checked:
            self.comboBox_regiao.setEditable(True)
        else:
            self.comboBox_regiao.setEditable(False)


    @pyqtSignature("QString")
    def on_comboBox_regiao_editTextChanged(self, text):
        print u'Texto editado: %s' % text

Na linha 57 é implementado o sinal editTextChanged, no ComboBox região, para verificar alterações nos elementos deste objeto. O console baixo mostra o que acontece quando a string do ComboBox é editada, conforme a figura do diálogo, no inicio deste texto:

./dialog_vendedor
Estado texto alterado: Acre
O elemento 0 foi highlighted...
O elemento 5 foi highlighted...
Estado texto alterado: Ceará
Estado texto activated: Ceará
Região texto alterado: Nordeste
Texto editado: Nordeste 
Texto editado: Nordeste é
Texto editado: Nordeste é 
Texto editado: Nordeste é q
Texto editado: Nordeste é qu
Texto editado: Nordeste é que
Texto editado: Nordeste é quen
Texto editado: Nordeste é quent
Texto editado: Nordeste é quente

Saída
Estado: Ceará
Índice: 5
Região: Nordeste é quente
Índice: 2

Alguns Comentários e Recomendações

Não tenho dedicado muito espaço aos métodos das classes apresentadas, me limitando mais especificamente aos sinais gerados pelos widgets. Bom isto se deve a dois motivos muito simples:

  • são muitos métodos: Se fosse apresentar todos os métodos, este texto mais se aproximaria de uma tradução da documentação do PyQt. Não que a ideia não seja interessante, mas reconheço que não sou o indivíduo mais indicado para este trabalho;
  • é necessário ler a documentação: por mais que dê exemplos e apresente alguns aspectos deste bind (PyQt) de certo não alcançarei todas as nuances das classes apresentadas. Por isto é fortemente recomendado a leitura da documentação oficial.

No entanto vou listar alguns métodos bastantes uteis dos ComboBox, mas nem de longe alcançareis todos:

[TABLE=32]

Como disse estes são apenas alguns métodos e com apenas algumas de suas opções. Métodos como o findText ainda suportam as flags: Qt.MatchFlags flags = Qt.MatchExactly | Qt.MatchCaseSensitive, não apresentadas na tabela acima.

Este post tem 2 comentários

  1. willian

    Já pensou em publicar um livro sobre PyQt4, seus posts já dão um excelente material inicial, tenho certeza que editoras como a novatec se ficariam interessados pelo assunto.

  2. rudsonalves

    Nem chegou perto Willian. PyQt é um universo bem maior do que abordei. Tão maior que entre um texto e outro, sempre fico me perguntando “e agora, qual será o próximo?”, dado a diversidade de tópicos disponíveis. Mas valeu a confiança.

Deixe um comentário

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