Crear una calculadora de suma sencilla con ImGui

Vamos a implementar una función de suma con dos campos de entrada numérica, un símbolo + en medio y un botón de igual. Al introducir dos números y pulsar =, el resultado del cálculo se mostrará en un tercer recuadro de entrada.

Aunque la funcionalidad es muy simple, este ejemplo nos sirve para aprender los controles de formulario básicos de ImGui.

Primero veamos una captura de pantalla del programa en ejecución

Es un ejemplo muy reducido. La mayor parte del código coincide con el ejercicio de la clase anterior; solo cambia la sección de renderizado de la interfaz. También hemos añadido variables para guardar los valores numéricos y cambiado el tema a claro para que se parezca más a las aplicaciones GUI de escritorio habituales.

#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("Fallo al inicializar 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 Suma", nullptr, nullptr); // Tamaño y título de ventana
    if (!window)
    {
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);

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

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

    // Variables globales de la calculadora
    float num1 = 0.0f;    // Primer sumando
    float num2 = 0.0f;    // Segundo sumando
    float result = 0.0f;  // Resultado de la suma

    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("Panel de Control", nullptr, window_flags);

        // Título de la calculadora
        ImGui::Text("Introduce dos números"); // Texto estático, ocupa una línea completa
	ImGui::Spacing();// Añadir espacio vertical

        // Primer campo de entrada, ancho de 120 píxeles
	ImGui::SetNextItemWidth(120);// Define el ancho del siguiente widget, no genera contenido visible
	ImGui::InputFloat("##num1", &num1);// Campo de entrada de coma flotante vinculado a num1, etiqueta oculta, línea propia

        // Dibujar el signo más en la misma línea
	ImGui::SameLine(); // El siguiente control se dibuja en la misma fila; sin esto hay salto de línea automático
	ImGui::Text(" + "); // Signo + en la misma línea que el primer recuadro

        // Segundo campo de entrada numérica
	ImGui::SameLine(); // Hay que llamarlo antes de cada widget que quieras alinear horizontalmente
        ImGui::SetNextItemWidth(120);// Establecer ancho del segundo campo
        ImGui::InputFloat("##num2", &num2);

        // Botón igual, ejecuta la suma al pulsarlo
        ImGui::SameLine();
        if (ImGui::Button(" = ", ImVec2(40, 0)))
        {
            // Calcular la suma y asignarla a la variable de resultado
            result = num1 + num2;
        }

        // Campo de resultado solo lectura, muestra dos decimales, prohibida edición manual
        ImGui::SameLine();
        ImGui::SetNextItemWidth(180);
        ImGui::InputFloat("##result", &result, 0.0f, 0.0f, "%.2f", ImGuiInputTextFlags_ReadOnly);

        ImGui::End();

	// Recuperar los estilos temporales guardados
        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;
}Lenguaje del código: C++ (cpp)

Para activar el tema claro solo tienes que modificar esta línea: ImGui::StyleColorsLight(); // Cambiar la interfaz al tema de colores claros

Para ajustar el título y tamaño de ventana edita esta línea: GLFWwindow* window = glfwCreateWindow(400, 60, «Calculadora de Suma», nullptr, nullptr); // Define ancho, alto y texto del título de ventana

ImGui::Text("Introduce dos números");

ImGui::Spacing(); // Crear margen vertical entre el título y los campos de entrada inferioresLenguaje del código: PHP (php)

Esta línea imprime texto fijo en la primera fila y luego inserta un margen vertical en la línea siguiente.

Consulta los comentarios del código superior para ver otras propiedades de los widgets. Por defecto, cada Text, InputFloat y Button ocupa una línea independiente. Si no quieres salto de línea, llama a ImGui::SameLine(); antes de dibujar cada elemento que quieras poner en la misma fila.

Usa SetNextItemWidth() si necesitas definir manualmente el ancho del próximo componente de interfaz.

Funcionamiento del clic en botón

if (ImGui::Button(" = ", ImVec2(40, 0)))
 {
            // Calcular la suma de los dos valores y guardarla en la variable resultado
            result = num1 + num2;
 }Lenguaje del código: C++ (cpp)

En este fragmento, ImGui::Button(» = «, ImVec2(40, 0)) genera un botón interactivo. El primer argumento es el texto que se muestra, el segundo establece ancho y alto; un alto de 0 significa que se adapta automáticamente al tamaño estándar del widget.

Esta función solo devuelve true al realizar un clic completo (pulsar y soltar el ratón sobre el botón); en cualquier otro estado devuelve false. Cuando el valor retornado es true, se ejecuta todo el código dentro de las llaves {}.

Piensa en todo el proceso como un bucle de renderizado continuo: la interfaz se refresca en cada fotograma, ejecutando todo el código del while en cada actualización. Si el usuario no interactúa, la pantalla se ve igual en cada ciclo. Si pulsa el botón en un fotograma, ImGui::Button() devuelve true y se ejecuta la lógica de cálculo.

El código del botón suma los valores vinculados a los dos campos de entrada, almacena el total en result y luego renderiza el campo de salida en la misma fila.

ImGui::SameLine();
ImGui::SetNextItemWidth(180);
ImGui::InputFloat("##result", &result, 0.0f, 0.0f, "%.2f", ImGuiInputTextFlags_ReadOnly);Lenguaje del código: C++ (cpp)

Este código permanece en la misma fila que el botón igual y muestra el valor calculado en el tercer recuadro, configurado como solo lectura.

Al terminar el renderizado de un fotograma, en el siguiente refresco se mantendrá el resultado anterior si el usuario no realiza ninguna acción nueva.

Este sistema de renderizado es idéntico al de los videojuegos; las animaciones de los juegos funcionan con este mismo mecanismo de actualización constante de imágenes.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *