Использование распространённых виджетов ImGui

Сначала очистим все элементы управления из предыдущего урока и создадим простейшее пустое окно без каких-либо компонентов.

#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
#pragma execution_character_set("utf-8")

#include <GLFW/glfw3.h>
#include "imgui.h"
#include "backends/imgui_impl_glfw.h"
#include "backends/imgui_impl_opengl3.h"
#include <cstdio>
#include <string>
#include <fstream>
#include <windows.h>
#include <io.h>
#include <commdlg.h>  // Заголовок необходим для диалогов работы с файлами

#include <iostream>
using namespace std;

// Настройка шрифта для исправления искажения символов "??" при вводе текста
// Укажите путь к шрифту под вашу операционную систему или используйте системный шрифт по умолчанию
void SetupFont(ImGuiIO& io)
{
    // Стандартный путь к китайскому шрифту в Windows
    const char* font_path = "C:/Windows/Fonts/msyh.ttc"; // Microsoft YaHei
    float font_size = 18.0f;

    // Загрузка набора часто используемых упрощённых китайских символов
    ImVector<ImWchar> ranges;
    ImFontGlyphRangesBuilder builder;
    builder.AddRanges(io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
    builder.BuildRanges(&ranges);

    // Загрузка пользовательского шрифта
    io.Fonts->AddFontFromFileTTF(font_path, font_size, nullptr, ranges.Data);

    // При необходимости многоязычной поддержки можно добавить:
    // io.Fonts->AddFontFromFileTTF(font_path, font_size, nullptr, io.Fonts->GetGlyphRangesJapanese());
    // io.Fonts->AddFontFromFileTTF(font_path, font_size, nullptr, io.Fonts->GetGlyphRangesKorean());
}


int main()
{

    if (!glfwInit())
    {
        printf("Ошибка инициализации 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(800, 600, "Заголовок", nullptr, nullptr);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);

    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    ImGui::StyleColorsLight();

    SetupFont(io); // Загрузка шрифта для исправления искажения текста

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

    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("Заголовок", nullptr, window_flags);

        // Начало области отрисовки элементов интерфейса

        // Конец области элементов

        ImGui::End();
        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)

Далее мы создадим виджеты ImGui по одному.

Текстовый виджет

ImGui::Text("Привет, мир %d", 123);Code language: PHP (php)

Текст выводится слева направо, начиная с верхнего левого угла окна.

Кнопка

        // Отобразить кнопку, внутренний код выполняется при нажатии
        if (ImGui::Button("Сохранить"))
        {
            // Код здесь запустится после клика
        }Code language: PHP (php)

Существует огромное множество виджетов, давайте рассмотрим полный пример ниже, который выводит все распространённые компоненты сразу.

#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
#pragma execution_character_set("utf-8")

#include <GLFW/glfw3.h>
#include "imgui.h"
#include "backends/imgui_impl_glfw.h"
#include "backends/imgui_impl_opengl3.h"
#include <cstdio>
#include <string>
#include <cstring>
#include <windows.h>
#include <io.h>
#include <iostream>
using namespace std;

// Настройка шрифта для исправления искажения символов "??" при вводе текста
// Укажите путь к шрифту под вашу операционную систему или используйте системный шрифт по умолчанию
void SetupFont(ImGuiIO& io)
{
    // Стандартный путь к китайскому шрифту в Windows
    const char* font_path = "C:/Windows/Fonts/msyh.ttc"; // Microsoft YaHei
    float font_size = 18.0f;

    // Загрузка набора часто используемых упрощённых китайских символов
    ImVector<ImWchar> ranges;
    ImFontGlyphRangesBuilder builder;
    builder.AddRanges(io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
    builder.BuildRanges(&ranges);

    // Загрузка пользовательского шрифта
    io.Fonts->AddFontFromFileTTF(font_path, font_size, nullptr, ranges.Data);

    // При необходимости многоязычной поддержки можно добавить:
    // io.Fonts->AddFontFromFileTTF(font_path, font_size, nullptr, io.Fonts->GetGlyphRangesJapanese());
    // io.Fonts->AddFontFromFileTTF(font_path, font_size, nullptr, io.Fonts->GetGlyphRangesKorean());
}

// ===================== Глобальные переменные, привязанные к виджетам =====================
char buf[256] = "Тестовый текст однострочного поля ввода";
char bufMulti[1024] = "Многострочное текстовое поле\nВторая строка\nТретья строка, тест китайских символов";
float fVal = 0.5f;
int iVal = 50;
bool checkBox1 = false;
bool checkBox2 = true;
int radioIdx = 0;
int comboSel = 0;
ImVec4 color = ImVec4(0.2f, 0.7f, 0.9f, 1.0f);
bool showPopupWin = false;
bool showModal = false;
int tabIndex = 0;
float progress = 0.35f;

int main()
{
    SetConsoleOutputCP(65001);
    if (!glfwInit())
    {
        printf("Ошибка инициализации 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(1000, 700, "Демо всех распространённых виджетов ImGui", nullptr, nullptr);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);

    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    ImGui::StyleColorsLight();

    SetupFont(io);

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

    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("Основное окно", nullptr, window_flags);

        // ========== 1. Верхняя панель меню ==========
        if (ImGui::BeginMenuBar())
        {
            if (ImGui::BeginMenu("Файл"))
            {
                if (ImGui::MenuItem("Создать", "Ctrl+N")) {}
                if (ImGui::MenuItem("Сохранить", "Ctrl+S")) {}
                ImGui::Separator();
                if (ImGui::MenuItem("Выход"))
                    glfwSetWindowShouldClose(window, true);
                ImGui::EndMenu();
            }
            if (ImGui::BeginMenu("Инструменты"))
            {
                if (ImGui::MenuItem("Открыть пример всплывающего окна"))
                    showPopupWin = true;
                ImGui::EndMenu();
            }
            ImGui::EndMenuBar();
        }
        ImGui::Spacing();

        // ========== 2. Базовые текстовые виджеты ==========
        ImGui::Text("===== Текстовые виджеты =====");
        ImGui::Text("Обычный текст Привет мир %d", 123);
        ImGui::TextColored(ImVec4(1, 0, 0, 1), "Красный цветной текст");
        ImGui::TextDisabled("Серый отключённый текст");
        ImGui::BulletText("Маркированный пункт 1");
        ImGui::BulletText("Маркированный пункт 2");
        ImGui::Spacing();

        // ========== 3. Группа кнопок ==========
        ImGui::Text("===== Кнопки =====");
        if (ImGui::Button("Обычная кнопка"))
            cout << "Нажата обычная кнопка" << endl;
        ImGui::SameLine();
        if (ImGui::SmallButton("Маленькая кнопка"))
            cout << "Нажата маленькая кнопка" << endl;
        ImGui::SameLine();
        if (ImGui::Button("Широкая кнопка", ImVec2(120, 0)))
            cout << "Нажата кнопка с пользовательской шириной" << endl;
        ImGui::Spacing();

        // ========== 4. Поля ввода ==========
        ImGui::Text("===== Поля ввода =====");
        ImGui::InputText("Однострочный ввод", buf, IM_ARRAYSIZE(buf));
        ImGui::InputTextWithHint("Поле с подсказкой", "Введите содержимое...", buf, IM_ARRAYSIZE(buf));
        ImGui::InputFloat("Ввод дробного числа", &fVal);
        ImGui::InputInt("Ввод целого числа", &iVal);
        ImGui::Spacing();
        ImGui::Text("Многострочное текстовое поле:");
        ImVec2 multiSize = ImVec2(500, 80);
        ImGui::InputTextMultiline("##multi", bufMulti, IM_ARRAYSIZE(bufMulti), multiSize);
        ImGui::Spacing();

        // ========== 5. Ползунки, полосы перетаскивания ==========
        ImGui::Text("===== Ползунки / Элементы перетаскивания =====");
        ImGui::SliderFloat("Дробный ползунок", &fVal, 0.0f, 1.0f);
        ImGui::SliderInt("Целый ползунок", &iVal, 0, 100);
        ImGui::DragFloat("Перетаскиваемое дробное поле", &fVal, 0.01f);
        ImGui::DragInt("Перетаскиваемое целое поле", &iVal, 1.0f);
        ImGui::Spacing();

        // ========== 6. Флажки, радиокнопки ==========
        ImGui::Text("===== Флажки & Радиокнопки =====");
        ImGui::Checkbox("Флажок A", &checkBox1);
        ImGui::Checkbox("Флажок B", &checkBox2);
        ImGui::Text("Группа радиокнопок:");
        ImGui::RadioButton("Вариант 1", &radioIdx, 0); ImGui::SameLine();
        ImGui::RadioButton("Вариант 2", &radioIdx, 1); ImGui::SameLine();
        ImGui::RadioButton("Вариант 3", &radioIdx, 2);
        ImGui::Spacing();

        // ========== 7. Выпадающий список Combo ==========
        ImGui::Text("===== Выпадающий список Combo =====");
        const char* items[] = { "Вариант A", "Вариант B", "Вариант C", "Вариант D" };
        ImGui::Combo("Выбор из списка", &comboSel, items, IM_ARRAYSIZE(items));
        ImGui::Spacing();

        // ========== 8. Выбор цвета ==========
        ImGui::Text("===== Редактор цвета =====");
        ImGui::ColorEdit4("Цвет RGBA", (float*)&color);
        ImGui::ColorButton("Превью цвета", color);
        ImGui::Spacing();

        // ========== 9. Полоса прогресса, разделители ==========
        ImGui::Text("===== Полоса прогресса / Разделители =====");
        ImGui::ProgressBar(progress, ImVec2(300, 0));
        ImGui::Text("Значение прогресса: %.2f", progress);
        ImGui::Separator(); // Горизонтальный разделитель
        ImGui::Spacing();

        // ========== 10. Сворачиваемые древовидные узлы ==========
        ImGui::Text("===== Сворачиваемые панели-деревья =====");
        if (ImGui::CollapsingHeader("Сворачиваемая панель – кликните для раскрытия"))
        {
            ImGui::Text("Содержимое внутри панели");
            ImGui::Button("Кнопка внутри панели");
        }
        if (ImGui::TreeNode("Древовидный узел"))
        {
            ImGui::BulletText("Подпункт 1");
            ImGui::BulletText("Подпункт 2");
            ImGui::TreePop();
        }
        ImGui::Spacing();

        // ========== 11. Вкладки TabBar ==========
        ImGui::Text("===== Вкладки Tab =====");
        ImGui::BeginTabBar("TabBar");
        if (ImGui::BeginTabItem("Вкладка 1"))
        {
            ImGui::Text("Содержимое вкладки 1");
            ImGui::EndTabItem();
        }
        if (ImGui::BeginTabItem("Вкладка 2"))
        {
            ImGui::Text("Содержимое вкладки 2");
            ImGui::EndTabItem();
        }
        ImGui::EndTabBar();
        ImGui::Spacing();

        // ========== 12. Таблица Table ==========
        ImGui::Text("===== Виджет таблицы =====");
        if (ImGui::BeginTable("table1", 3, ImGuiTableFlags_Borders))
        {
            ImGui::TableSetupColumn("№");
            ImGui::TableSetupColumn("Название");
            ImGui::TableSetupColumn("Значение");
            ImGui::TableHeadersRow();

            // Строка 1
            ImGui::TableNextRow();
            ImGui::TableNextColumn(); ImGui::Text("1");
            ImGui::TableNextColumn(); ImGui::Text("Тест A");
            ImGui::TableNextColumn(); ImGui::Text("%.2f", fVal);
            // Строка 2
            ImGui::TableNextRow();
            ImGui::TableNextColumn(); ImGui::Text("2");
            ImGui::TableNextColumn(); ImGui::Text("Тест B");
            ImGui::TableNextColumn(); ImGui::Text("%d", iVal);
            ImGui::EndTable();
        }
        ImGui::Spacing();

        // ========== 13. Контекстное меню по правому клику ==========
        ImGui::Text("===== Меню по правому клику (нажмите правую кнопку мыши на этом тексте) =====");
        if (ImGui::IsItemClicked(ImGuiMouseButton_Right))
            ImGui::OpenPopup("RightMenu");
        if (ImGui::BeginPopup("RightMenu"))
        {
            ImGui::MenuItem("Пункт контекстного меню 1");
            ImGui::MenuItem("Пункт контекстного меню 2");
            ImGui::Separator();
            ImGui::MenuItem("Закрыть меню");
            ImGui::EndPopup();
        }
        ImGui::Spacing();

        // ========== 14. Обычное всплывающее окно (немодальное) ==========
        if (showPopupWin)
        {
            ImGui::OpenPopup("PopupWindow");
            showPopupWin = false;
        }
        if (ImGui::BeginPopup("PopupWindow"))
        {
            ImGui::Text("Немодальное окно, основное окно остаётся активным");
            if (ImGui::Button("Закрыть всплывающее окно"))
                ImGui::CloseCurrentPopup();
            ImGui::EndPopup();
        }

        // ========== 15. Модальное диалоговое окно Modal ==========
        if (ImGui::Button("Открыть модальное окно"))
            showModal = true;
        if (showModal)
        {
            ImGui::OpenPopup("ModalDialog");
            showModal = false;
        }
        if (ImGui::BeginPopupModal("Модальный диалог", nullptr, ImGuiWindowFlags_AlwaysAutoResize))
        {
            ImGui::Text("Модальное окно блокирует основное, его нужно закрыть первым");
            if (ImGui::Button("ОК", ImVec2(120, 0)))
            {
                ImGui::CloseCurrentPopup();
            }
            ImGui::EndPopup();
        }

        ImGui::End();
        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)

Вы можете постепенно изучать и пробовать работу каждого виджета.

Библиотека виджетов очень обширная, полностью удовлетворяет задачи разработки простых служебных программ. Здесь есть сворачиваемые деревья, вкладки, все элементы форм: одно- и многострочные поля ввода, радиокнопки, флажки, выпадающие списки, полосы прогресса, сворачиваемые панели, таблицы, контекстные меню, редакторы цвета и многое другое. Попробуйте поэкспериментировать самостоятельно.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *