ImTui
人気のDear ImGuiライブラリをベースにした即時モードTUIライブラリ。デバッグインターフェースやリアルタイムモニタリングツールに最適。
GitHub概要
ggerganov/imtui
ImTui: Immediate Mode Text-based User Interface C++ Library
スター3,332
ウォッチ46
フォーク141
作成日:2019年12月8日
言語:C++
ライセンス:MIT License
トピックス
texttuiuiuser-interface
スター履歴
データ取得日時: 2025/7/25 11:08
ImTui
ImTuiは、人気のDear ImGuiライブラリをターミナル環境に移植した即時モードTUIライブラリです。ImGuiのシンプルで直感的なAPIを維持しながら、ターミナルアプリケーション開発を可能にします。
特徴
即時モードGUI
- 即時モード: 状態管理が不要で、毎フレーム描画するシンプルなアプローチ
- ImGui互換: Dear ImGuiのAPIに基づいた使い慣れたインターフェース
- 軽量: ヘッダーオンリーライブラリで簡単統合
豊富なウィジェット
- 基本ウィジェット: ボタン、テキスト入力、スライダー、チェックボックス
- レイアウト: 行、列、ウィンドウ、メニューバー
- データ表示: テーブル、リスト、ツリー
- プロット: グラフ、チャート表示機能
インストール
vcpkg経由
vcpkg install imtui
CMake手動ビルド
git clone https://github.com/ggerganov/imtui
cd imtui
mkdir build && cd build
cmake ..
make -j4
基本的な使用方法
Hello World
#include "imtui/imtui.h"
#include "imtui/imtui-impl-ncurses.h"
int main() {
IMTUI_CHECKVERSION();
ImTui::CreateContext();
auto screen = ImTui_ImplNcurses_Init(true);
ImTui_ImplText_Init();
bool demo_open = true;
while (demo_open) {
ImTui_ImplNcurses_NewFrame();
ImTui_ImplText_NewFrame();
ImTui::NewFrame();
ImTui::SetNextWindowPos(ImVec2(4, 2), ImGuiCond_Once);
ImTui::SetNextWindowSize(ImVec2(50, 10), ImGuiCond_Once);
if (ImTui::Begin("Hello ImTui!")) {
ImTui::Text("Hello, Terminal UI!");
static float value = 0.5f;
ImTui::SliderFloat("Value", &value, 0.0f, 1.0f);
if (ImTui::Button("Exit")) {
demo_open = false;
}
}
ImTui::End();
ImTui::Render();
ImTui_ImplText_RenderDrawData(ImTui::GetDrawData(), screen);
ImTui_ImplNcurses_DrawScreen();
}
ImTui_ImplText_Shutdown();
ImTui_ImplNcurses_Shutdown();
ImTui::DestroyContext();
return 0;
}
システム監視ツール
#include "imtui/imtui.h"
#include "imtui/imtui-impl-ncurses.h"
#include <vector>
#include <cmath>
#include <chrono>
class SystemMonitor {
private:
std::vector<float> cpu_history;
std::vector<float> memory_history;
std::chrono::steady_clock::time_point last_update;
public:
SystemMonitor() : last_update(std::chrono::steady_clock::now()) {
cpu_history.reserve(100);
memory_history.reserve(100);
}
void update() {
auto now = std::chrono::steady_clock::now();
if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_update).count() > 100) {
// シミュレートしたCPU使用率
float cpu_usage = 30.0f + 20.0f * sin(cpu_history.size() * 0.1f);
float memory_usage = 60.0f + 15.0f * cos(memory_history.size() * 0.05f);
if (cpu_history.size() >= 100) cpu_history.erase(cpu_history.begin());
if (memory_history.size() >= 100) memory_history.erase(memory_history.begin());
cpu_history.push_back(cpu_usage);
memory_history.push_back(memory_usage);
last_update = now;
}
}
void render() {
ImTui::SetNextWindowPos(ImVec2(2, 1), ImGuiCond_Once);
ImTui::SetNextWindowSize(ImVec2(76, 20), ImGuiCond_Once);
if (ImTui::Begin("System Monitor")) {
// CPU使用率
if (!cpu_history.empty()) {
ImTui::Text("CPU Usage: %.1f%%", cpu_history.back());
ImTui::PlotLines("##cpu", cpu_history.data(), cpu_history.size(),
0, nullptr, 0.0f, 100.0f, ImVec2(0, 40));
}
ImTui::Separator();
// メモリ使用率
if (!memory_history.empty()) {
ImTui::Text("Memory Usage: %.1f%%", memory_history.back());
ImTui::PlotLines("##memory", memory_history.data(), memory_history.size(),
0, nullptr, 0.0f, 100.0f, ImVec2(0, 40));
}
ImTui::Separator();
// システム情報
ImTui::Text("Uptime: 2 days, 4 hours");
ImTui::Text("Load Average: 0.45, 0.38, 0.32");
if (ImTui::Button("Refresh")) {
// リフレッシュ処理
}
ImTui::SameLine();
if (ImTui::Button("Clear History")) {
cpu_history.clear();
memory_history.clear();
}
}
ImTui::End();
}
};
int main() {
IMTUI_CHECKVERSION();
ImTui::CreateContext();
auto screen = ImTui_ImplNcurses_Init(true);
ImTui_ImplText_Init();
SystemMonitor monitor;
bool running = true;
while (running) {
ImTui_ImplNcurses_NewFrame();
ImTui_ImplText_NewFrame();
ImTui::NewFrame();
monitor.update();
monitor.render();
// メインメニュー
if (ImTui::BeginMainMenuBar()) {
if (ImTui::BeginMenu("File")) {
if (ImTui::MenuItem("Exit", "Ctrl+Q")) {
running = false;
}
ImTui::EndMenu();
}
ImTui::EndMainMenuBar();
}
ImTui::Render();
ImTui_ImplText_RenderDrawData(ImTui::GetDrawData(), screen);
ImTui_ImplNcurses_DrawScreen();
}
ImTui_ImplText_Shutdown();
ImTui_ImplNcurses_Shutdown();
ImTui::DestroyContext();
return 0;
}
デバッグ・診断ツール
#include "imtui/imtui.h"
#include "imtui/imtui-impl-ncurses.h"
#include <map>
#include <string>
#include <sstream>
class DebugConsole {
private:
std::vector<std::string> log_messages;
std::map<std::string, float> variables;
char input_buffer[256] = "";
public:
DebugConsole() {
variables["frame_time"] = 16.67f;
variables["fps"] = 60.0f;
variables["memory_mb"] = 256.0f;
log("Debug console initialized");
}
void log(const std::string& message) {
log_messages.push_back(message);
if (log_messages.size() > 1000) {
log_messages.erase(log_messages.begin());
}
}
void set_variable(const std::string& name, float value) {
variables[name] = value;
log("Variable '" + name + "' set to " + std::to_string(value));
}
void render() {
ImTui::SetNextWindowPos(ImVec2(1, 1), ImGuiCond_Once);
ImTui::SetNextWindowSize(ImVec2(78, 22), ImGuiCond_Once);
if (ImTui::Begin("Debug Console")) {
// 変数ウォッチ
if (ImTui::CollapsingHeader("Variables", ImGuiTreeNodeFlags_DefaultOpen)) {
for (auto& [name, value] : variables) {
ImTui::Text("%-20s: %.3f", name.c_str(), value);
ImTui::SameLine();
if (ImTui::SmallButton(("Edit##" + name).c_str())) {
// 編集ダイアログを開く
}
}
}
ImTui::Separator();
// ログビューア
if (ImTui::CollapsingHeader("Log", ImGuiTreeNodeFlags_DefaultOpen)) {
ImTui::BeginChild("LogScrolling", ImVec2(0, 120), false, ImGuiWindowFlags_HorizontalScrollbar);
for (const auto& message : log_messages) {
ImTui::Text("%s", message.c_str());
}
if (ImTui::GetScrollY() >= ImTui::GetScrollMaxY()) {
ImTui::SetScrollHereY(1.0f);
}
ImTui::EndChild();
}
ImTui::Separator();
// コマンド入力
ImTui::Text("Command:");
ImTui::SameLine();
if (ImTui::InputText("##command", input_buffer, sizeof(input_buffer),
ImGuiInputTextFlags_EnterReturnsTrue)) {
process_command(input_buffer);
input_buffer[0] = '\0';
ImTui::SetKeyboardFocusHere(-1);
}
ImTui::SameLine();
if (ImTui::Button("Execute")) {
process_command(input_buffer);
input_buffer[0] = '\0';
}
ImTui::SameLine();
if (ImTui::Button("Clear Log")) {
log_messages.clear();
}
}
ImTui::End();
}
private:
void process_command(const std::string& command) {
log("> " + command);
std::istringstream iss(command);
std::string cmd;
iss >> cmd;
if (cmd == "set") {
std::string var_name;
float value;
if (iss >> var_name >> value) {
set_variable(var_name, value);
} else {
log("Usage: set <variable> <value>");
}
} else if (cmd == "get") {
std::string var_name;
if (iss >> var_name) {
auto it = variables.find(var_name);
if (it != variables.end()) {
log(var_name + " = " + std::to_string(it->second));
} else {
log("Variable '" + var_name + "' not found");
}
} else {
log("Usage: get <variable>");
}
} else if (cmd == "help") {
log("Available commands:");
log(" set <var> <value> - Set variable value");
log(" get <var> - Get variable value");
log(" help - Show this help");
log(" clear - Clear log");
} else if (cmd == "clear") {
log_messages.clear();
} else if (!cmd.empty()) {
log("Unknown command: " + cmd + " (type 'help' for commands)");
}
}
};
エコシステム
バックエンド
- ncurses: Unix/Linux環境での標準バックエンド
- Windows Console: Windows環境サポート
- SDL: 将来的なGUIサポートの可能性
関連プロジェクト
- Dear ImGui: オリジナルのImGuiライブラリ
- ImPlot: プロット機能の拡張
- ImGuiColorTextEdit: テキストエディタ機能
利点
- 学習コストが低い: ImGuiユーザーには馴染みのあるAPI
- 即時モード: 複雑な状態管理が不要
- デバッグに最適: リアルタイムパラメータ調整に優れている
- 軽量: 最小限の依存関係
- クロスプラットフォーム: Windows、Linux、macOSサポート
制約事項
- 限定的なウィジェット: ncursesの制約により一部機能が制限
- パフォーマンス: 毎フレーム描画のためCPU使用率が高い
- カスタマイズ: テーマやスタイルのカスタマイズが限定的
- 複雑なレイアウト: 高度なレイアウト機能は限定的
他のライブラリとの比較
項目 | ImTui | FTXUI | ncurses |
---|---|---|---|
パラダイム | 即時モード | 宣言的 | 手続き的 |
学習コスト | 低(ImGui経験者) | 中 | 高 |
デバッグ用途 | ★★★★★ | ★★★☆☆ | ★★☆☆☆ |
パフォーマンス | ★★☆☆☆ | ★★★★☆ | ★★★★★ |
カスタマイズ性 | ★★☆☆☆ | ★★★★☆ | ★★★★★ |
まとめ
ImTuiは、Dear ImGuiの使いやすさをターミナル環境に持ち込んだ革新的なライブラリです。特にデバッグツール、プロトタイピング、リアルタイムモニタリングアプリケーションの開発に優れており、即時モードGUIの利点を活かした迅速な開発が可能です。ImGuiの経験があれば、すぐに生産性の高いTUIアプリケーション開発を始められます。