Combo Boxes
BeginCombo() / EndCombo()
Manually control combo box contents:IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0);
IMGUI_API void EndCombo();
const char*
required
Widget label
const char*
required
Text displayed in the combo box before opening
ImGuiComboFlags
Optional combo flags (see below)
const char* items[] = { "Apple", "Banana", "Cherry", "Dragon Fruit" };
static int item_current_idx = 0;
const char* combo_preview_value = items[item_current_idx];
if (ImGui::BeginCombo("Fruit", combo_preview_value)) {
for (int n = 0; n < IM_COUNTOF(items); n++) {
const bool is_selected = (item_current_idx == n);
if (ImGui::Selectable(items[n], is_selected))
item_current_idx = n;
// Set initial focus when opening the combo
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
Only call
EndCombo() if BeginCombo() returns true!Simple Combo() Functions
Convenience wrappers for common use cases:IMGUI_API bool Combo(const char* label, int* current_item, const char* const items[], int items_count,
int popup_max_height_in_items = -1);
IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros,
int popup_max_height_in_items = -1);
IMGUI_API bool Combo(const char* label, int* current_item,
const char* (*getter)(void* user_data, int idx), void* user_data,
int items_count, int popup_max_height_in_items = -1);
- Array of Strings
- Null-Separated String
- Getter Function
const char* items[] = { "AAA", "BBB", "CCC", "DDD" };
static int item_current = 0;
ImGui::Combo("Combo", &item_current, items, IM_COUNTOF(items));
static int item_current = 0;
ImGui::Combo("Combo", &item_current, "One\0Two\0Three\0Four\0\0");
const char* items[] = { "AAA", "BBB", "CCC" };
static int item_current = 0;
auto getter = [](void* data, int n) -> const char* {
return ((const char**)data)[n];
};
ImGui::Combo("Combo", &item_current, getter, items, IM_COUNTOF(items));
Combo Flags
Popup Alignment
// Align popup to left (useful if combo is wider than popup)
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_PopupAlignLeft);
Height
// Small popup (4 items visible)
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_HeightSmall);
// Regular popup (8 items visible, default)
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_HeightRegular);
// Large popup (20 items visible)
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_HeightLarge);
// Largest popup (as many fitting items as possible)
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_HeightLargest);
Button Style
// No arrow button
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_NoArrowButton);
// No preview text (button only)
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_NoPreview);
// Width matches preview text width
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_WidthFitPreview);
Combo with Search Filter
Add filtering to combo box contents:const char* items[] = { "Apple", "Apricot", "Banana", "Blueberry", "Cherry" };
static int item_current_idx = 0;
const char* combo_preview_value = items[item_current_idx];
if (ImGui::BeginCombo("Fruits", combo_preview_value)) {
static ImGuiTextFilter filter;
// Focus search box when opening
if (ImGui::IsWindowAppearing()) {
ImGui::SetKeyboardFocusHere();
filter.Clear();
}
// Search box
filter.Draw("##filter", -FLT_MIN);
// Filtered items
for (int n = 0; n < IM_COUNTOF(items); n++) {
const bool is_selected = (item_current_idx == n);
if (filter.PassFilter(items[n])) {
if (ImGui::Selectable(items[n], is_selected))
item_current_idx = n;
}
}
ImGui::EndCombo();
}
List Boxes
BeginListBox() / EndListBox()
Create a scrollable list:IMGUI_API bool BeginListBox(const char* label, const ImVec2& size = ImVec2(0, 0));
IMGUI_API void EndListBox();
ImVec2
size.x > 0.0f: Custom widthsize.x < 0.0f or -FLT_MIN: Right-alignsize.x = 0.0f: Use current ItemWidthsize.y > 0.0f: Custom heightsize.y < 0.0f or -FLT_MIN: Bottom-alignsize.y = 0.0f: Default height (~7 items)
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE" };
static int item_selected_idx = 0;
if (ImGui::BeginListBox("##listbox")) {
for (int n = 0; n < IM_COUNTOF(items); n++) {
const bool is_selected = (item_selected_idx == n);
if (ImGui::Selectable(items[n], is_selected))
item_selected_idx = n;
// Set initial focus when opening
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndListBox();
}
Custom Sized List Box
// Full width, 5 items tall
if (ImGui::BeginListBox("##listbox2", ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing()))) {
for (int n = 0; n < IM_COUNTOF(items); n++) {
bool is_selected = (item_selected_idx == n);
if (ImGui::Selectable(items[n], is_selected))
item_selected_idx = n;
}
ImGui::EndListBox();
}
Simple ListBox() Function
Convenience wrapper:IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[],
int items_count, int height_in_items = -1);
IMGUI_API bool ListBox(const char* label, int* current_item,
const char* (*getter)(void* user_data, int idx), void* user_data,
int items_count, int height_in_items = -1);
const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange" };
static int item_current = 1;
ImGui::ListBox("Listbox", &item_current, items, IM_COUNTOF(items), 4);
Highlighting Hovered Items
static int item_selected = 0;
static int item_highlighted = -1;
if (ImGui::BeginListBox("##listbox")) {
for (int n = 0; n < IM_COUNTOF(items); n++) {
const bool is_selected = (item_selected == n);
ImGuiSelectableFlags flags = 0;
if (item_highlighted == n)
flags |= ImGuiSelectableFlags_Highlight;
if (ImGui::Selectable(items[n], is_selected, flags))
item_selected = n;
if (ImGui::IsItemHovered())
item_highlighted = n;
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndListBox();
}
Multi-Column Lists
Combine list boxes with tables:if (ImGui::BeginListBox("##listbox3", ImVec2(-FLT_MIN, 0))) {
if (ImGui::BeginTable("##table", 3)) {
static int selected = -1;
for (int i = 0; i < 10; i++) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
char label[32];
sprintf(label, "Item %d", i);
if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
selected = i;
ImGui::TableNextColumn();
ImGui::Text("Column 2");
ImGui::TableNextColumn();
ImGui::Text("Data %d", i * 10);
}
ImGui::EndTable();
}
ImGui::EndListBox();
}
Complete Example
void ShowComboListDemo() {
ImGui::Begin("Combo & List Demo");
// Simple combo
ImGui::Text("Simple Combo:");
const char* items[] = { "Apple", "Banana", "Cherry", "Dragon Fruit" };
static int combo_current = 0;
ImGui::Combo("Fruit", &combo_current, items, IM_COUNTOF(items));
ImGui::Spacing();
// Custom combo with BeginCombo/EndCombo
ImGui::Text("Custom Combo:");
static int item_current_idx = 0;
const char* combo_preview = items[item_current_idx];
if (ImGui::BeginCombo("Custom", combo_preview, ImGuiComboFlags_HeightLarge)) {
for (int n = 0; n < IM_COUNTOF(items); n++) {
const bool is_selected = (item_current_idx == n);
if (ImGui::Selectable(items[n], is_selected))
item_current_idx = n;
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
// List box
ImGui::Text("List Box:");
static int list_current = 0;
if (ImGui::BeginListBox("##listbox", ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing()))) {
for (int n = 0; n < IM_COUNTOF(items); n++) {
const bool is_selected = (list_current == n);
if (ImGui::Selectable(items[n], is_selected))
list_current = n;
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndListBox();
}
ImGui::End();
}
Performance Tips
For large lists, useImGuiListClipper to only render visible items:
if (ImGui::BeginListBox("##large_list", ImVec2(-FLT_MIN, 0))) {
ImGuiListClipper clipper;
clipper.Begin(1000); // 1000 items
while (clipper.Step()) {
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
char label[32];
sprintf(label, "Item %d", i);
if (ImGui::Selectable(label, selected == i))
selected = i;
}
}
ImGui::EndListBox();
}
Best Practices
Use
BeginCombo() / EndCombo() for full control over combo contents, including filtering and custom rendering.Always call
EndCombo() or EndListBox() only if the corresponding Begin function returned true.Call
SetItemDefaultFocus() on the selected item to ensure proper keyboard navigation when the popup opens.