Basic Tables
BeginTable() / EndTable()
Create a table:IMGUI_API bool BeginTable(const char* str_id, int columns, ImGuiTableFlags flags = 0,
const ImVec2& outer_size = ImVec2(0.0f, 0.0f), float inner_width = 0.0f);
IMGUI_API void EndTable();
const char*
required
Unique identifier for the table
int
required
Number of columns
ImGuiTableFlags
Table behavior flags (see below)
ImVec2
Outer size of the table container
Only call
EndTable() if BeginTable() returns true!Three Ways to Populate Tables
- Method 1: TableSetColumnIndex()
- Method 2: TableNextColumn()
- Method 3: Auto-wrap
Most flexible - use in loops:
if (ImGui::BeginTable("table1", 3)) {
for (int row = 0; row < 4; row++) {
ImGui::TableNextRow();
for (int column = 0; column < 3; column++) {
ImGui::TableSetColumnIndex(column);
ImGui::Text("Row %d Column %d", row, column);
}
}
ImGui::EndTable();
}
More convenient for manual submission:
if (ImGui::BeginTable("table2", 3)) {
for (int row = 0; row < 4; row++) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("Row %d", row);
ImGui::TableNextColumn();
ImGui::Text("Content");
ImGui::TableNextColumn();
ImGui::Text("123.456");
}
ImGui::EndTable();
}
TableNextColumn() automatically wraps:
if (ImGui::BeginTable("table3", 3)) {
for (int item = 0; item < 14; item++) {
ImGui::TableNextColumn();
ImGui::Text("Item %d", item);
}
ImGui::EndTable();
}
Table Rows
TableNextRow()
Advance to the next row:IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f);
ImGuiTableRowFlags
Optional row flags (e.g.,
ImGuiTableRowFlags_Headers)float
Minimum row height (includes CellPadding.y * 2)
if (ImGui::BeginTable("table", 2)) {
// Regular row
ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::Text("Normal");
ImGui::TableNextColumn(); ImGui::Text("Row");
// Tall row
ImGui::TableNextRow(0, 50.0f);
ImGui::TableNextColumn(); ImGui::Text("Tall");
ImGui::TableNextColumn(); ImGui::Text("Row");
ImGui::EndTable();
}
Table Columns
TableSetupColumn()
Define column properties:IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0,
float init_width_or_weight = 0.0f, ImGuiID user_id = 0);
const char*
required
Column label (used for headers)
ImGuiTableColumnFlags
Column behavior flags
float
Initial width (pixels) or weight (ratio)
if (ImGui::BeginTable("table", 3, ImGuiTableFlags_Resizable)) {
ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("Size", ImGuiTableColumnFlags_WidthFixed, 100.0f);
ImGui::TableSetupColumn("Type");
ImGui::TableHeadersRow();
for (int row = 0; row < 5; row++) {
ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::Text("File%d", row);
ImGui::TableNextColumn(); ImGui::Text("%d KB", row * 10);
ImGui::TableNextColumn(); ImGui::Text("Document");
}
ImGui::EndTable();
}
TableHeadersRow()
Submit a row with header cells:IMGUI_API void TableHeadersRow();
if (ImGui::BeginTable("table", 3)) {
ImGui::TableSetupColumn("ID");
ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("Value");
ImGui::TableHeadersRow();
// ... table contents ...
ImGui::EndTable();
}
Table Flags
Sizing Flags
// Default: columns are resizable
ImGuiTableFlags_Resizable
// Fit all columns within available width
ImGuiTableFlags_SizingFixedFit
// Columns stretch to fit available width
ImGuiTableFlags_SizingFixedSame
// Each column takes an equal portion
ImGuiTableFlags_SizingStretchProp
// All columns same width, stretch to fit
ImGuiTableFlags_SizingStretchSame
Border Flags
// All borders
ImGuiTableFlags_Borders
// Equivalent to:
ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersOuterV |
ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_BordersOuterH
// Horizontal borders
ImGuiTableFlags_BordersH
ImGuiTableFlags_BordersInnerH
ImGuiTableFlags_BordersOuterH
// Vertical borders
ImGuiTableFlags_BordersV
ImGuiTableFlags_BordersInnerV
ImGuiTableFlags_BordersOuterV
// No borders in body (only in headers)
ImGuiTableFlags_NoBordersInBody
Scrolling Flags
// Enable horizontal scrolling
ImGuiTableFlags_ScrollX
// Enable vertical scrolling
ImGuiTableFlags_ScrollY
Row Flags
// Alternating row background colors
ImGuiTableFlags_RowBg
// Make rows selectable
ImGuiTableFlags_RowClickable
Sorting Flags
// Enable sorting (single column)
ImGuiTableFlags_Sortable
// Allow sorting by multiple columns (Shift+Click)
ImGuiTableFlags_SortMulti
// Allow removing sort by Ctrl+clicking headers
ImGuiTableFlags_SortTristate
Scrolling Tables
Create tables with frozen headers and scrolling:if (ImGui::BeginTable("table", 3,
ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders,
ImVec2(0, 300))) {
ImGui::TableSetupColumn("ID");
ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("Value");
ImGui::TableHeadersRow();
for (int row = 0; row < 100; row++) {
ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::Text("%04d", row);
ImGui::TableNextColumn(); ImGui::Text("Item %d", row);
ImGui::TableNextColumn(); ImGui::Text("%d", row * 100);
}
ImGui::EndTable();
}
TableSetupScrollFreeze()
Freeze columns and rows:IMGUI_API void TableSetupScrollFreeze(int cols, int rows);
if (ImGui::BeginTable("table", 4, ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) {
ImGui::TableSetupScrollFreeze(1, 1); // Freeze first column and first row
ImGui::TableSetupColumn("ID");
ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("Age");
ImGui::TableSetupColumn("City");
ImGui::TableHeadersRow();
// ... table contents ...
ImGui::EndTable();
}
Sorting
TableGetSortSpecs()
Get sorting specifications:IMGUI_API ImGuiTableSortSpecs* TableGetSortSpecs();
struct MyItem {
int id;
const char* name;
int value;
};
static ImVector<MyItem> items;
if (ImGui::BeginTable("table", 3, ImGuiTableFlags_Sortable | ImGuiTableFlags_RowBg)) {
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort);
ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("Value");
ImGui::TableHeadersRow();
// Get sort specs
if (ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs()) {
if (sort_specs->SpecsDirty) {
// Sort your data
// sort_specs->Specs[0].ColumnUserID
// sort_specs->Specs[0].ColumnIndex
// sort_specs->Specs[0].SortDirection (ImGuiSortDirection_Ascending/Descending)
// ... perform sort ...
sort_specs->SpecsDirty = false;
}
}
// Display items
for (const MyItem& item : items) {
ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::Text("%d", item.id);
ImGui::TableNextColumn(); ImGui::Text("%s", item.name);
ImGui::TableNextColumn(); ImGui::Text("%d", item.value);
}
ImGui::EndTable();
}
Column Flags
Width
// Auto-sizing width
ImGuiTableColumnFlags_WidthStretch // Default
// Fixed width
ImGuiTableColumnFlags_WidthFixed
Resizing
// User cannot resize this column
ImGuiTableColumnFlags_NoResize
// Double-click to auto-fit
ImGuiTableColumnFlags_NoAutoResize
Sorting
// Default sort direction
ImGuiTableColumnFlags_DefaultSort
// User cannot sort this column
ImGuiTableColumnFlags_NoSort
// Prefer ascending sort
ImGuiTableColumnFlags_PreferSortAscending
// Prefer descending sort
ImGuiTableColumnFlags_PreferSortDescending
Visibility
// Start hidden
ImGuiTableColumnFlags_DefaultHide
// Disable ability to hide column
ImGuiTableColumnFlags_NoHide
Advanced Features
Context Menu
Enable right-click column menu:ImGui::BeginTable("table", 3, ImGuiTableFlags_ContextMenuInBody);
Hideable Columns
if (ImGui::BeginTable("table", 4, ImGuiTableFlags_Hideable)) {
ImGui::TableSetupColumn("Column 1");
ImGui::TableSetupColumn("Column 2", ImGuiTableColumnFlags_DefaultHide);
ImGui::TableSetupColumn("Column 3");
ImGui::TableSetupColumn("Column 4");
ImGui::TableHeadersRow();
// Right-click on headers to show/hide columns
// ...
ImGui::EndTable();
}
Reorderable Columns
ImGui::BeginTable("table", 3, ImGuiTableFlags_Reorderable);
Complete Example
void ShowTableDemo() {
ImGui::Begin("Table Demo");
// Basic table with borders
if (ImGui::BeginTable("table1", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("Age");
ImGui::TableSetupColumn("City");
ImGui::TableHeadersRow();
ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::Text("Alice");
ImGui::TableNextColumn(); ImGui::Text("25");
ImGui::TableNextColumn(); ImGui::Text("New York");
ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::Text("Bob");
ImGui::TableNextColumn(); ImGui::Text("30");
ImGui::TableNextColumn(); ImGui::Text("London");
ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::Text("Charlie");
ImGui::TableNextColumn(); ImGui::Text("35");
ImGui::TableNextColumn(); ImGui::Text("Tokyo");
ImGui::EndTable();
}
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
// Scrolling table with frozen header
if (ImGui::BeginTable("table2", 4,
ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg |
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable,
ImVec2(0, 200))) {
ImGui::TableSetupScrollFreeze(0, 1); // Freeze header row
ImGui::TableSetupColumn("ID");
ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("Value");
ImGui::TableSetupColumn("Status");
ImGui::TableHeadersRow();
for (int row = 0; row < 50; row++) {
ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::Text("%04d", row);
ImGui::TableNextColumn(); ImGui::Text("Item %d", row);
ImGui::TableNextColumn(); ImGui::Text("%d", row * 100);
ImGui::TableNextColumn(); ImGui::Text(row % 2 ? "Active" : "Inactive");
}
ImGui::EndTable();
}
ImGui::End();
}
Performance Tips
For very large tables, useImGuiListClipper:
if (ImGui::BeginTable("large_table", 3, ImGuiTableFlags_ScrollY)) {
ImGui::TableSetupColumn("ID");
ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("Value");
ImGui::TableHeadersRow();
ImGuiListClipper clipper;
clipper.Begin(10000); // 10,000 items
while (clipper.Step()) {
for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) {
ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::Text("%d", row);
ImGui::TableNextColumn(); ImGui::Text("Item %d", row);
ImGui::TableNextColumn(); ImGui::Text("%d", row * 10);
}
}
ImGui::EndTable();
}
Best Practices
Always call
EndTable() only if BeginTable() returns true.Use
ImGuiTableFlags_SizingStretchProp for responsive tables that adapt to window size.Call
TableSetupColumn() before TableHeadersRow() to define column properties and labels.Combine
ImGuiTableFlags_ScrollY with TableSetupScrollFreeze(0, 1) to keep headers visible while scrolling.