Implementação e Manipulação de QComboBox em Aplicações PyQt5

Visão Geral do Widget

O QComboBox é um dos componentes fundamantais na criação de interfaces gráficas desktop. Ele funciona como uma união de um campo de edição de texto e uma caixa de lista suspensa, permitindo que o usuário selecione uma única opção entre diversas alternativas predefinidas ou insira novos valores manualmente.

Criação e Gerenciamento Básico

A instanciação requer um pai (geralmente uma janela principal ou widget contêiner). Abaixo segue um exemplo demonstrando configurações primárias, manipulação de itens e estilização simples.

import sys
from PyQt5.QtWidgets import QWidget, QApplication, QComboBox, QPushButton, QLabel
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon

class InterfaceDeTeste(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Exemplo de ComboBox')
        self.setGeometry(100, 100, 500, 350)
        
        # Instanciação do Controle
        self.combo_sel = QComboBox(self)
        self.combo_sel.move(50, 50)
        self.combo_sel.resize(200, 40)
        
        # Botão para ações programáticas
        self.btn_acao = QPushButton('Atualizar', self)
        self.btn_acao.move(50, 150)
        self.btn_acao.clicked.connect(self.manipular_combo)
        
        # Configurações visuais
        self.combo_sel.setIconSize(24, 24)
        self.combo_sel.setEditable(True)
        self.combo_sel.setFrame(False)

    def manipular_combo(self):
        # Adicionação de Strings Simples
        self.combo_sel.addItem("Opção Alpha")
        
        # Adição com Ícone e Texto
        self.combo_sel.addItem(QIcon(), "Item Gráfico")
        
        # Adição em Lote (Lista)
        opcoes = ["Novo Item A", "Novo Item B", "Novo Item C"]
        self.combo_sel.addItems(opcoes)
        
        # Inserção em índice específico
        self.combo_sel.insertItem(1, "Inserção no Meio")
        
        # Remover item pelo índice
        self.combo_sel.removeItem(2)
        
        # Limpeza total da lista
        # self.combo_sel.clear()
        
        print(f"Total de itens: {self.combo_sel.count()}")
        print(f"Valor atual: {self.combo_sel.currentText()}")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    janela = InterfaceDeTeste()
    janela.show()
    sys.exit(app.exec_())

Hierarquia de Dados Dependentes

Um caso de uso comum envolve listas dependentes, onde a seleção de um controle altera as opções disponíveis no segundo. Isso é frequentemente utilizado em formulários fiscais (Estado -> Cidade -> CEP).

No exemplo a seguir, utilizamos dois objetos QComboBox. O primeiro seleciona uma região macro, e o segundo popula dinamicamente as cidades correspondentes armazenadas em dicionários aninhados.

import sys
from PyQt5.QtWidgets import QWidget, QApplication, QComboBox, QHBoxLayout, QVBoxLayout, QLabel
from PyQt5.QtCore import Qt

class AppHierarquia(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Seleção Hierárquica')
        self.layout = QVBoxLayout()
        
        # Dados estruturados: Região -> (Cidade, Código)
        self.dados_geograficos = {
            'Região Norte': {'Manaus': '92', 'Belém': '91'},
            'Região Sul': {'Porto Alegre': '51', 'Curitiba': '41'},
            'Região Leste': {'Rio de Janeiro': '21', 'Vitória': '27'},
        }

        # Layout horizontal para os controles
        self.contenedor = QHBoxLayout()
        self.layout.addLayout(self.contenedor)
        
        # Combo Regiões
        self.cbx_regiao = QComboBox()
        self.cbx_regiao.setMinimumWidth(200)
        self.cbx_regiao.addItems(list(self.dados_geograficos.keys()))
        
        # Combo Cidades (Inicialmente vazio)
        self.cbx_cidade = QComboBox()
        self.cbx_cidade.setMinimumWidth(200)
        
        self.contenedor.addWidget(QLabel("Região:"))
        self.contenedor.addWidget(self.cbx_regiao)
        self.contenedor.addWidget(QLabel("Cidade:"))
        self.contenedor.addWidget(self.cbx_cidade)
        
        self.init_connectors()
        self.setup_ui()

    def init_connectors(self):
        # Conecta o sinal quando o texto muda (útil para input editável) ou index mudou
        self.cbx_regiao.currentTextChanged.connect(self.atualizar_subniveis)
        
        # Precisamos obter dados associados à cidade
        self.cbx_cidade.currentIndexChanged.connect(self.exibir_info)

    def setup_ui(self):
        # Preenche a primeira camada inicialmente
        self.atualizar_subniveis("")

    def atualizar_subniveis(self, nome_regiao):
        if not nome_regiao:
            return
            
        # Bloqueia sinais durante a atualização para evitar loops
        old_blocked = self.cbx_cidade.blockSignals(True)
        
        self.cbx_cidade.clear()
        
        # Busca subitens no dicionário
        sub_itens = self.dados_geograficos.get(nome_regiao, {})
        for cidade, codigo in sub_itens.items():
            # Valor adicionado como dado associado (role user data)
            self.cbx_cidade.addItem(cidade, codigo)
            
        self.cbx_cidadde.blockSignals(old_blocked)

    def exibir_info(self, indice):
        if indice >= 0:
            codigo = self.cbx_cidade.itemData(indice)
            print(f"Cidade Selecionada ID: {codigo}")
        else:
            print("Nenhuma seleção válida.")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = AppHierarquia()
    demo.show()
    sys.exit(app.exec_())

Manipluação de Sinais e Eventos

Para interagir com a lógica da aplicação, monitorar os eventos gerados pelo widget é essencial. O PyQt5 fornece várias sobrecargas de slots:

  • activated(int) / activated(str): Acionado quando o usuário clica em uma opção.
  • currentTextChanged(QString): Utilizado se o modo for editável.
  • highlighted(int): Dispara sempre que o mouse passa sobre um item da lista pendente.

A configuração correta depende se você deseja processar apenas seleções confirmadas ou também pré-seleções.

Tags: pyqt5 QComboBox UserInterface EventHandling DesktopDevelopment

Publicado em 10-19 16:53