Open kbirk opened 5 years ago
You may call Selectable() first which a non-visible label ("##title"
) and specify a custom size, and then draw your stuff over it. You'll need to know the size ahead and call the imgui_internal.h text drawing functions that handle clipping.
Sorry to revive an old post, but I run into the same issue and I more or less managed to make it work so I thought some people might want to know the following.
As stated above, using a non-visible label in Selectable, then drawing images/texts work, but the selectable label MUST be unique, otherwise only the first item can be selected. Here is a short example:
int i = 0;
for (std::vector<std::string>::iterator it = m_items.begin(); it != m_items.end(); ++it) {
std::string itemid = "##" + std::to_string(i);
if (ImGui::Selectable(itemid.c_str(), i == m_selectedItem)) {
m_selectedItem = i;
}
ImGui::SameLine();
ImGui::Text("Item: ");
ImGui::SameLine();
ImGui::Text((*it).c_str());
i++;
}
This only displays texts (or image/buttons/...) on the same line. To draw on separate lines you indeed need to move the cursor and set the clipping manually.
As stated above, using a non-visible label in Selectable, then drawing images/texts work, but the selectable label MUST be unique, otherwise only the first item can be selected. Here is a short example:
You can also use PushID()
, this is all explained in the FAQ
"Why are multiple widgets reacting when I interact with a single one? How can I have multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack..."
Sorry to revive this issue again, but I'm having a problem where if I specify the width of the selectable it stops being drawn above the items that I want, but if I don't specify it overflows into the next item.. Is there a better way to make images selectable?
Here is an example I got working. Creates a custom Selectable with 2 stacked text fields and a clickable button to the side that opens a modal dialog.
` auto pos = ImGui::GetCursorPos();
// selectable list
for (int n = 0; n < 10; n++)
{
ImGui::PushID(n);
char buf[32];
sprintf(buf, "##Object %d", n);
ImGui::SetCursorPos(ImVec2(pos.x, pos.y));
if (ImGui::Selectable(buf, n == selected, 0, ImVec2(width, 50))) {
selected = n;
}
ImGui::SetItemAllowOverlap();
ImGui::SetCursorPos(ImVec2(pos.x, pos.y));
ImGui::Text("foo");
ImGui::SetCursorPos(ImVec2(pos.x + 30, pos.y+5));
if(ImGui::Button("do thing", ImVec2(70, 30)))
{
ImGui::OpenPopup("Setup?");
selected = n;
printf("SETUP CLICKED %d\n", n);
}
if (ImGui::BeginPopupModal("Setup?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImVec2 pos_before = window->DC.CursorPos;
ImGui::Text("Setup Popup");
if (ImGui::Button("OK", ImVec2(120, 0))) { printf("OK PRESSED!\n"); ImGui::CloseCurrentPopup(); }
ImGui::EndPopup();
}
ImGui::SetCursorPos(ImVec2(pos.x, pos.y+20));
ImGui::Text("bar");
pos.y += 55;
ImGui::PopID();
}
`
I know this is an old one, but the above looks a bit too complicated, here's my solution (I use imgui Java bindings):
fun selectableButton(label: String, selected: Boolean, width: Float, height: Float, onSelect: (() -> Unit)? = null, content: (() -> Unit)? = null) {
val cursorPosX = ImGui.getCursorPosX()
if (ImGui.selectable(label, selected, ImGuiSelectableFlags.None, width, height)) {
onSelect?.invoke()
}
ImGui.sameLine()
val afterCursorPosX = ImGui.getCursorPosX()
ImGui.setCursorPosX(cursorPosX)
content?.invoke()
ImGui.sameLine()
ImGui.setCursorPosX(afterCursorPosX)
}
Is there a way to get
ImGui::Selectable
behavior but have the component be comprised of several other nested components?For example:
Where each
ImGui::Selectable
is contains anImGui::Image
and twoImGui::Text
calls but acts as a single "selectable" item.