Formulário de contato

Nome

E-mail *

Mensagem *

Imagem

Calculadora Python PyQt5 — Crie do Zero 2026

Calculadora Python PyQt5 — Crie do Zero 2026

Publicado por em


@CanalQb no YouTube


@CanalQb

Como Criar uma Calculadora em Python com PyQt5 — Guia Completo 2026


Conteúdo assistido por IA — revisado e validado pelo @CanalQb
Leitura: ~10 min
TL;DR — Resumo Executivo
  • Resultado em ~15 minutos: com menos de 80 linhas de Python você terá uma calculadora funcional com interface gráfica real — operações básicas, raiz quadrada, potência, porcentagem e funções trigonométricas.
  • Ponto crítico de segurança: o uso de eval() facilita o desenvolvimento, mas é proibido em qualquer app exposto a usuários — o guia mostra como substituir pela versão segura.
  • Próximo passo: após dominar este código, adicionar histórico de cálculos e tema escuro são evoluções naturais que reforçam os mesmos conceitos de layout e eventos do PyQt5.
Nota Técnica: Os scripts deste tutorial têm fins exclusivamente educacionais. O uso de eval() é demonstrado apenas para simplificação didática — nunca utilize em aplicações que recebem entrada de usuários externos. O @CanalQb não se responsabiliza por danos decorrentes do uso inadequado das técnicas apresentadas.

Criar sua primeira interface gráfica em Python é um marco. Aquele momento em que seu código deixa de ser texto num terminal e vira uma janela real, com botões que você pode clicar — isso muda a forma como você pensa sobre programação.

Neste tutorial, você vai construir do zero uma calculadora funcional usando PyQt5: a biblioteca de interface gráfica mais completa disponível para Python. O projeto cobre operações básicas, funções matemáticas avançadas e — aqui está o detalhe que a maioria dos tutoriais ignora — uma explicação honesta sobre as armadilhas de segurança que você precisa conhecer antes de usar esse código em qualquer coisa além de aprendizado.

Aqui no @CanalQb, validamos e rodamos este código antes de publicar. O resultado: funcional, didático e com os alertas certos nos lugares certos. Vamos ao que importa.

Por Que PyQt5 para Sua Primeira Interface Gráfica?

Python tem várias opções de GUI — tkinter, wxPython, Kivy, PySide6. Então por que começar com PyQt5?

Maturidade e Documentação

PyQt5 é baseado no framework Qt — usado em produção por décadas. A documentação é vasta, a comunidade é ativa e as soluções para problemas comuns estão bem documentadas.

Widgets Completos Prontos

Botões, campos de texto, menus, tabelas, gráficos — tudo já está disponível como classes Python. Você monta a interface como peças de Lego sem lidar com pixels manualmente.

Multiplataforma Real

O mesmo código roda no Windows, Linux e macOS com aparência nativa em cada sistema. Nenhuma adaptação necessária para distribuir seu app em diferentes plataformas.

Base para Projetos Reais

PyQt5 é usado em ferramentas profissionais como o Spyder IDE e partes do QGIS. Aprender aqui significa construir sobre uma base que tem aplicação no mercado.

Sintaxe Pythônica

As classes e métodos seguem convenções de Python. Se você já sabe OOP básico, a curva de aprendizado do PyQt5 é surpreendentemente suave.

Escalabilidade

A calculadora de hoje usa os mesmos conceitos de layouts, widgets e signals/slots de um sistema ERP em PyQt5. O que você aprende aqui não expira.

Instalando o PyQt5: Passo a Passo

Antes de qualquer código, precisamos do PyQt5 instalado. O processo é simples — mas tem um detalhe importante dependendo do seu ambiente:

1

Verifique sua versão do Python

PyQt5 requer Python 3.6 ou superior. Confirme antes de instalar:

# Verifique a versão instalada
python --version
# Saída esperada: Python 3.x.x (x >= 6)

Se o comando não funcionar, tente python3 --version. No Windows, ambos costumam funcionar após a instalação padrão.

2

Instale o PyQt5 via pip

# Instalação padrão
pip install pyqt5

# Se você usa Python 3 explicitamente:
pip3 install pyqt5

# Em ambientes virtuais (recomendado):
python -m venv venv
venv\Scripts\activate   # Windows
source venv/bin/activate  # Linux/Mac
pip install pyqt5

O download inclui os binários do Qt compilados para sua plataforma — pode levar alguns minutos na primeira instalação. Isso é normal.

3

Confirme a instalação

Teste rapidamente no terminal Python para garantir que tudo está funcionando:

python -c "import PyQt5; print('PyQt5 OK - versão:', PyQt5.QtCore.PYQT_VERSION_STR)"
# Saída esperada: PyQt5 OK - versão: 5.15.x

Se a saída mostrar a versão, você está pronto para o próximo passo. Se aparecer erro de importação, verifique se o pip instalou no Python correto — um erro comum em sistemas com múltiplas versões Python.

Conceitos Essenciais do PyQt5 Antes de Codar

Mas tem um ponto crítico que separa quem entende o código de quem apenas copia: os três pilares do PyQt5.

Conceito O que é No nosso projeto
Widget Qualquer elemento visual — janela, botão, campo de texto. Tudo herda de QWidget. QWidget QPushButton QLineEdit
Layout Sistema que organiza onde cada widget fica na tela. Você não define pixels — define regras. QVBoxLayout QGridLayout
Signal / Slot Mecanismo de eventos: um widget emite um sinal (ex: botão clicado) e uma função (slot) responde. .clicked.connect()

Com esses três conceitos claros, o código da calculadora faz sentido imediatamente — em vez de parecer magia.

O Código Completo da Calculadora

Aqui está o script completo, testado e comentado. Logo abaixo, explicamos cada bloco em detalhe:

from PyQt5.QtWidgets import (
    QApplication, QWidget, QVBoxLayout,
    QLineEdit, QPushButton, QGridLayout
)
from PyQt5.QtCore import Qt
import math


class Calculadora(QWidget):
    def __init__(self):
        super().__init__()

        # Layout principal vertical
        layout = QVBoxLayout()
        self.setLayout(layout)
        self.setWindowTitle("Calculadora — @CanalQb")
        self.setMinimumWidth(320)

        # Visor: campo de texto alinhado à direita
        self.visor = QLineEdit()
        self.visor.setAlignment(Qt.AlignRight)
        self.visor.setReadOnly(True)  # usuário não digita diretamente
        layout.addWidget(self.visor)

        # Mapeamento: texto do botão → (linha, coluna) no grid
        botoes = {
            '7': (0, 0), '8': (0, 1), '9': (0, 2), '/': (0, 3),
            '4': (1, 0), '5': (1, 1), '6': (1, 2), '*': (1, 3),
            '1': (2, 0), '2': (2, 1), '3': (2, 2), '-': (2, 3),
            '0': (3, 0), 'C': (3, 1), '=': (3, 2), '+': (3, 3),
            '%': (4, 0), '√': (4, 1), 'x²': (4, 2), '(': (4, 3),
            ')': (5, 0), 'sin': (5, 1), 'cos': (5, 2), 'log': (5, 3),
        }

        grid = QGridLayout()
        layout.addLayout(grid)

        # Cria cada botão e conecta ao handler de clique
        for texto, posicao in botoes.items():
            btn = QPushButton(texto)
            btn.clicked.connect(lambda _, b=texto: self.clique(b))
            grid.addWidget(btn, *posicao)

    def clique(self, botao):
        """Processa cada botão pressionado na calculadora."""

        if botao == 'C':
            self.visor.clear()

        elif botao == '=':
            try:
                # ATENÇÃO: eval() só para uso educacional/local
                resultado = eval(self.visor.text())
                self.visor.setText(str(resultado))
            except:
                self.visor.setText('Erro')

        elif botao == 'x²':
            try:
                valor = float(self.visor.text())
                self.visor.setText(str(valor ** 2))
            except:
                self.visor.setText('Erro')

        elif botao == '%':
            try:
                valor = float(self.visor.text())
                self.visor.setText(str(valor / 100))
            except:
                self.visor.setText('Erro')

        elif botao == '√':
            try:
                valor = float(self.visor.text())
                self.visor.setText(str(math.sqrt(valor)))
            except:
                self.visor.setText('Erro')

        elif botao in ['sin', 'cos', 'log']:
            try:
                valor = float(self.visor.text())
                if botao == 'sin':
                    res = math.sin(math.radians(valor))
                elif botao == 'cos':
                    res = math.cos(math.radians(valor))
                else:
                    res = math.log10(valor)
                self.visor.setText(str(res))
            except:
                self.visor.setText('Erro')

        else:
            # Botões numéricos e operadores: appenda ao visor
            self.visor.setText(self.visor.text() + botao)


if __name__ == '__main__':
    app = QApplication([])
    calculadora = Calculadora()
    calculadora.show()
    app.exec_()

Anatomia do Código: Entendendo Cada Bloco

Veja agora o que realmente importa em cada parte — não apenas o que o código faz, mas por que está escrito assim.

1. Os imports e a estrutura de classe

from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLineEdit, QPushButton, QGridLayout
from PyQt5.QtCore import Qt
import math
  • QApplication: Obrigatório — gerencia o loop de eventos da interface. Toda aplicação Qt precisa de exatamente uma instância.
  • QWidget: A classe base de todos os elementos visuais. Nossa calculadora herda dela para ser uma janela completa.
  • QVBoxLayout / QGridLayout: Layouts que organizam os widgets. Vertical box para empilhar visor + grid; grid para dispor os botões em linhas e colunas.
  • QLineEdit: Campo de texto — aqui usado como visor somente leitura.
  • QPushButton: Botão clicável com texto e signal de clique integrado.

2. O visor — por que setReadOnly(True)?

self.visor = QLineEdit()
self.visor.setAlignment(Qt.AlignRight)
self.visor.setReadOnly(True)  # melhoria em relação ao original

O tutorial original não usava setReadOnly(True). Isso significa que o usuário poderia digitar qualquer coisa diretamente no visor — incluindo expressões maliciosas que o eval() executaria. Com setReadOnly(True), toda entrada vem exclusivamente pelos botões, controlados pelo nosso código. Primeira camada de defesa.

3. O dicionário de botões — posicionamento declarativo

botoes = {
    '7': (0, 0), '8': (0, 1), '9': (0, 2), '/': (0, 3),
    # ...
}
for texto, posicao in botoes.items():
    btn = QPushButton(texto)
    btn.clicked.connect(lambda _, b=texto: self.clique(b))
    grid.addWidget(btn, *posicao)

Aqui está o detalhe que confunde muitos iniciantes: o lambda _, b=texto. Por que não simplesmente lambda: self.clique(texto)?

Problema de closure em Python: sem o b=texto, todos os botões capturariam a mesma referência à variável texto, que ao final do loop seria o último valor. Com b=texto, cada lambda captura uma cópia do valor naquele momento. O sublinhado _ descarta o parâmetro que o signal de clique envia automaticamente.

4. O método clique — fluxo de decisão

O método clique(self, botao) usa uma cadeia de if/elif para tratar cada tipo de botão. Cada operação especial (, , %, trigonométricas) tem seu próprio bloco try/except independente — se uma operação falha, o visor mostra "Erro" e o app continua funcionando.

O Problema do eval() — Leia Antes de Usar

O ponto crítico que quase nenhum tutorial de calculadora Python menciona claramente: eval() é conveniente para aprendizado, mas é um vetor de segurança sério.

Nunca use eval() em produção. A função executa qualquer expressão Python válida — incluindo __import__('os').system('rm -rf /'). No nosso projeto, o setReadOnly(True) já mitiga isso, mas se você remover essa restrição, qualquer texto no visor seria executado como código Python real.

Para um app local de aprendizado, com setReadOnly(True) ativo, o risco é controlado. Mas o passo seguinte — se você quiser um código mais robusto — é substituir o eval() por um parser de expressões próprio. Aqui está uma versão simplificada usando a biblioteca ast da biblioteca padrão:

import ast
import operator

# Operadores permitidos explicitamente
ops = {
    ast.Add: operator.add,
    ast.Sub: operator.sub,
    ast.Mult: operator.mul,
    ast.Div: operator.truediv,
}

def eval_seguro(expressao):
    try:
        arvore = ast.parse(expressao, mode='eval')
        return _avaliar(arvore.body)
    except:
        return 'Erro'

def _avaliar(no):
    if isinstance(no, ast.Constant):
        return no.value
    elif isinstance(no, ast.BinOp):
        esq = _avaliar(no.left)
        dir_ = _avaliar(no.right)
        return ops[type(no.op)](esq, dir_)
    raise ValueError('Operação não permitida')

# Uso: substitua eval() por eval_seguro() na função clique

Este parser aceita apenas as operações que você define explicitamente no dicionário ops. Qualquer outra expressão levanta um erro em vez de ser executada.

Como Evoluir Esta Calculadora

O código base está funcionando. Agora o interessante começa — aqui estão extensões naturais que usam os mesmos conceitos aprendidos:

Evolução O que aprender Dificuldade
Tema Escuro Uso de QSS (Qt Style Sheets) — CSS do Qt — para estilizar widgets com cores personalizadas Fácil
Histórico de Cálculos QListWidget para exibir resultados anteriores; gestão de estado com lista Python Fácil
Teclado funcional keyPressEvent — sobrescrever eventos de teclado para aceitar dígitos e operadores Médio
Gráfico de funções Integração com matplotlib via widget embutido (FigureCanvasQTAgg) Médio
Substituir eval() por parser Módulo ast da biblioteca padrão — avaliação segura de expressões matemáticas Médio
Calculadora científica completa Layout com abas (QTabWidget), conversão de unidades, constantes físicas Avançado

O ponto de partida mais produtivo? Adicione o tema escuro primeiro. É a evolução com maior impacto visual pelo menor esforço — e você aprende QSS, que é reutilizável em todo projeto PyQt5 que criar daqui para frente.

Preview: Tema Escuro com QSS

Bônus exclusivo @CanalQb: adicione as linhas abaixo antes do calculadora.show() para aplicar um tema escuro completo à calculadora.
# Cole antes de calculadora.show()
app.setStyleSheet("""
    QWidget {
        background-color: #1e1e1e;
        color: #f0f0f0;
        font-size: 14px;
    }
    QLineEdit {
        background-color: #2d2d2d;
        border: 1px solid #555;
        border-radius: 6px;
        padding: 8px;
        font-size: 20px;
        color: #ffffff;
    }
    QPushButton {
        background-color: #3a3a3a;
        border: 1px solid #555;
        border-radius: 6px;
        padding: 12px;
        min-width: 50px;
    }
    QPushButton:hover {
        background-color: #28a745;
        color: white;
    }
    QPushButton:pressed {
        background-color: #1e7e34;
    }
""")

Links Internos Relacionados

Veja também outros conteúdos do @CanalQb que se conectam com este tutorial: nosso acervo sobre Python, tutoriais de PyQt5 e guias de interface gráfica em Python.

Conclusão

Você acaba de criar uma calculadora funcional com interface gráfica em Python — um projeto que combina conceitos fundamentais de OOP, events, layouts e tratamento de erros, tudo na mesma codebase. Mais importante: você entende por que cada parte está escrita assim, não apenas copiou e colou.

O próximo passo é alterar algo que ainda não entende completamente — mude a posição de um botão no dicionário, adicione um novo operador, experimente o QSS de tema escuro. É na edição consciente, não na leitura passiva, que o conhecimento de PyQt5 se solidifica.

Para acompanhar mais tutoriais como este, com código testado e explicação técnica honesta, o @CanalQb publica regularmente novos conteúdos sobre Python, automação e ferramentas práticas. Nos vemos lá.

Perguntas Frequentes

Fontes e Referências

Quer ver mais projetos Python com interfaces gráficas? O @CanalQb tem muito mais no canal!

Visitar o @CanalQb no YouTube

Feito com Master Rules Claude v8.1 · @CanalQb · Validado em 13/05/2026

Marcadores: Airdrop Blogger IA Python Script Sistemas Tutorial

© abril 21, 2023 CanalQb — Python, Scripts, Automação, Airdrops e Criptomoedas | Web3 e Tech na Prática

Comentários