Criar uma calculadora de soma simples com ImGui

Vamos implementar uma funcionalidade de soma com duas caixas de entrada numérica, um símbolo de mais no meio e um botão de igual. Ao digitar dois números e clicar no botão =, o resultado do cálculo aparecerá na terceira caixa de entrada.

A funcionalidade é bem básica, mas com esse exemplo conseguimos aprender os elementos de formulário fundamentais do ImGui.

Primeiro, confira uma captura de tela do programa em execução

Trata-se de um exemplo compacto. A maior parte do código é igual ao exercício da aula anterior; apenas a lógica de renderização da interface muda. Também adicionamos variáveis para armazenar os valores numéricos e trocamos o tema para claro, deixando o visual parecido com programas GUI comuns de desktop.

#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")

#include <GLFW/glfw3.h>
#include "imgui.h"
#include "backends/imgui_impl_glfw.h"
#include "backends/imgui_impl_opengl3.h"
#include <cstdio>

int main()
{
    if (!glfwInit())
    {
        printf("Falha ao inicializar o GLFW\n");
        return -1;
    }

    const char* glsl_version = "#version 330";
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    GLFWwindow* window = glfwCreateWindow(500, 200, "Calculadora de Soma", nullptr, nullptr); // Tamanho e título da janela
    if (!window)
    {
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);

    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
	ImGui::StyleColorsLight(); // Ativar tema claro

    ImGui_ImplGlfw_InitForOpenGL(window, true);
    ImGui_ImplOpenGL3_Init(glsl_version);

    // Variáveis globais da calculadora
    float num1 = 0.0f;    // Primeiro valor da soma
    float num2 = 0.0f;    // Segundo valor da soma
    float result = 0.0f;  // Resultado da soma dos dois números

    while (!glfwWindowShouldClose(window))
    {
        glfwPollEvents();

        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        ImGui::SetNextWindowPos(ImVec2(0, 0));
        ImGui::SetNextWindowSize(io.DisplaySize);

        ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration
            | ImGuiWindowFlags_NoMove
            | ImGuiWindowFlags_NoResize
            | ImGuiWindowFlags_NoSavedSettings;

        ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
        ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);

        ImGui::Begin("Painel de Controle", nullptr, window_flags);

        // Título da calculadora
        ImGui::Text("Digite dois números"); // Texto estático, ocupa uma linha inteira
	ImGui::Spacing();// Adicionar espaço vertical

        // Primeira caixa de entrada, largura de 120 pixels
	ImGui::SetNextItemWidth(120);// Define a largura do próximo widget, não gera conteúdo visível
	ImGui::InputFloat("##num1", &num1);// Caixa de entrada de ponto flutuante ligada à variável num1, rótulo oculto, linha própria

        // Desenhar o símbolo de mais na mesma linha
	ImGui::SameLine(); // O próximo elemento fica na mesma linha; sem essa chamada, quebra de linha automática
	ImGui::Text(" + "); // Símbolo de mais na mesma linha da primeira caixa

        // Segunda caixa de entrada numérica
	ImGui::SameLine(); // É necessário chamar antes de cada widget que queira alinhar horizontalmente
        ImGui::SetNextItemWidth(120);// Definir largura da segunda caixa
        ImGui::InputFloat("##num2", &num2);

        // Botão de igual, executa a soma ao ser clicado
        ImGui::SameLine();
        if (ImGui::Button(" = ", ImVec2(40, 0)))
        {
            // Calcular a soma e salvar na variável de resultado
            result = num1 + num2;
        }

        // Caixa de resultado apenas leitura, exibe duas casas decimais, edição manual bloqueada
        ImGui::SameLine();
        ImGui::SetNextItemWidth(180);
        ImGui::InputFloat("##result", &result, 0.0f, 0.0f, "%.2f", ImGuiInputTextFlags_ReadOnly);

        ImGui::End();

	// Restaurar os estilos temporários salvos
        ImGui::PopStyleVar(2);

        ImGui::Render();
        int width, height;
        glfwGetFramebufferSize(window, &width, &height);
        glViewport(0, 0, width, height);
        glClearColor(0.12f, 0.12f, 0.12f, 1.f);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

        glfwSwapBuffers(window);
    }

    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();
    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}Code language: C++ (cpp)

Para habilitar o tema claro basta alterar essa linha: ImGui::StyleColorsLight(); // Mudar a interface para o tema de cores claras

Para ajustar o título e o tamanho da janela edite essa linha: GLFWwindow* window = glfwCreateWindow(400, 60, “Calculadora de Soma”, nullptr, nullptr); // Define largura, altura e texto do título da janela

ImGui::Text("Digite dois números");

ImGui::Spacing(); // Criar margem vertical entre o título e as caixas de entrada abaixoCode language: PHP (php)

Essa linha imprime texto fixo na primeira linha e depois insere um espaço vertical na linha seguinte.

Veja os comentários do código acima para as outras propriedades dos widgets. Por padrão, cada Text, InputFloat e Button ocupa uma linha separada. Se quiser evitar quebrar a linha, chame ImGui::SameLine(); antes de desenhar cada elemento que ficará na mesma fila.

Use SetNextItemWidth() se precisar definir manualmente a largura do próximo componente de interface.

Como funciona o clique no botão

if (ImGui::Button(" = ", ImVec2(40, 0)))
 {
            // Calcular a soma dos dois valores e atribuir à variável de resultado
            result = num1 + num2;
 }Code language: C++ (cpp)

Nesse trecho, ImGui::Button(” = “, ImVec2(40, 0)) cria um botão interativo. O primeiro parâmetro é o texto visível, o segundo define largura e altura; altura igual a 0 significa ajuste automático ao tamanho padrão do widget.

Essa função só retorna true com um clique completo (pressionar e soltar o mouse sobre a área do botão); em todos os outros estados retorna false. Quando o valor retornado for true, todo o código dentro das chaves {} será executado.

Imagine todo o fluxo como um loop de renderização contínuo: a interface atualiza em cada quadro, rodando todo o código dentro do while a cada atualização. Se o usuário não fizer nenhuma ação, a tela permanecerá igual em cada ciclo. Se ele clicar no botão em um quadro, ImGui::Button() retorna true e a lógica de cálculo é executada.

O código dentro do botão soma os valores ligados às duas caixas de entrada, armazena o total em result e depois renderiza a caixa de saída na mesma linha.

ImGui::SameLine();
ImGui::SetNextItemWidth(180);
ImGui::InputFloat("##result", &result, 0.0f, 0.0f, "%.2f", ImGuiInputTextFlags_ReadOnly);Code language: C++ (cpp)

Esse código permanece na mesma linha do botão de igual e mostra o valor calculado na terceira caixa, configurada apenas para leitura.

Ao finalizar a renderização de um quadro, na próxima atualização o resultado anterior permanecerá visível se o usuário não realizar uma nova ação.

Esse sistema de renderização é igual ao usado em videogames; animações de jogos funcionam com esse mesmo mecanismo de atualização constante de imagens.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *