如何在ImGui中创建无重叠的双列按钮布局?
ImGui双列按钮布局重叠问题解决
我尝试用ImGui实现每行两个按钮的双列布局,第三个按钮自动换行,但目前按钮出现重叠、错位的问题。目标是仅通过Option方法完成布局,不在View中调用SameLine。
原实现代码
ImVec2 menuPos = { -10, 15 }; ImVec2 menuSize = { 475.f, 775.f }; bool Option(std::string option) { static int buttonCounter = 0; // 跟踪按钮位置的计数器 if (buttonCounter % 2 == 1) { ImGui::SameLine(); // 第二个按钮放在同一行 } else { ImGui::SetCursorPosX(70); // 第一个按钮对齐到行右侧 } ImGui::PushStyleColor(ImGuiCol_Button, pink); bool result = ImGui::Button(option.c_str(), { 190, 30 });//OffsetsXY for now ImGui::PopStyleColor(); buttonCounter++; return result; } void View() { ImGui::SetNextWindowPos(menuPos); ImGui::SetNextWindowSize(menuSize); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(ImColor(0, 0, 0, 175))); ImGui::PushStyleColor(ImGuiCol_Border, GetCurrentFadeColor()); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 2.f); if (ImGui::Begin("Background", 0, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize)) { DrawVerticalLineFromTop(GetCurrentFadeColor(), 50, 2.f, menuSize.y); Option("Option1"); Option("Option2"); Option("Option3"); Option("Option4"); Option("Option5"); Option("Option6"); Option("Option7"); } ImGui::PopStyleVar(); ImGui::PopStyleColor(2); ImGui::End(); }
预期布局:
Option Option Option Option Option Option Option ...
问题原因
- 静态计数器
buttonCounter仅控制X轴位置,未处理换行时的Y轴偏移,导致第三个按钮直接覆盖在第一行第一个按钮的位置。 SameLine()未指定第二个按钮的精确X位置,可能导致按钮间距混乱。- 静态计数器跨帧累加,会导致后续帧的按钮布局完全错位。
修复后的代码
ImVec2 menuPos = { -10, 15 }; ImVec2 menuSize = { 475.f, 775.f }; // 假设pink是已定义的颜色变量 ImVec4 pink = ImVec4(1.0f, 0.4f, 0.7f, 1.0f); bool Option(std::string option) { static int lastFrame = 0; static int buttonsInRow = 0; // 每帧重置行内按钮计数,避免跨帧状态残留 if (ImGui::GetFrameCount() != lastFrame) { lastFrame = ImGui::GetFrameCount(); buttonsInRow = 0; } const float buttonWidth = 190.0f; const float buttonHeight = 30.0f; const float startX = 70.0f; const float horizontalSpacing = 20.0f; // 按钮间水平间距 const float verticalSpacing = 10.0f; // 行与行之间的垂直间距 // 行内满2个按钮时,换行并重置计数 if (buttonsInRow == 2) { ImGui::SetCursorPosY(ImGui::GetCursorPosY() + buttonHeight + verticalSpacing); buttonsInRow = 0; } if (buttonsInRow == 0) { // 设置每行第一个按钮的X位置 ImGui::SetCursorPosX(startX); } else { // 第二个按钮放在同一行,指定精确X位置 ImGui::SameLine(); ImGui::SetCursorPosX(startX + buttonWidth + horizontalSpacing); } ImGui::PushStyleColor(ImGuiCol_Button, pink); bool result = ImGui::Button(option.c_str(), { buttonWidth, buttonHeight }); ImGui::PopStyleColor(); buttonsInRow++; return result; } void View() { ImGui::SetNextWindowPos(menuPos); ImGui::SetNextWindowSize(menuSize); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(ImColor(0, 0, 0, 175))); ImGui::PushStyleColor(ImGuiCol_Border, GetCurrentFadeColor()); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 2.f); if (ImGui::Begin("Background", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize)) { DrawVerticalLineFromTop(GetCurrentFadeColor(), 50, 2.f, menuSize.y); Option("Option1"); Option("Option2"); Option("Option3"); Option("Option4"); Option("Option5"); Option("Option6"); Option("Option7"); } ImGui::PopStyleVar(); ImGui::PopStyleColor(2); ImGui::End(); }
修复要点
- 新增
buttonsInRow跟踪当前行的按钮数量,满2个则通过调整Y轴实现换行。 - 用
ImGui::GetFrameCount()重置每帧的计数状态,避免跨帧的布局混乱。 - 精确指定第二个按钮的X位置,保证按钮间距一致。
- 增加垂直间距参数,让行与行之间的布局更美观。
内容的提问来源于stack exchange,提问作者Avi
相关产品推荐
相关产品推荐

