ImGUI技术咨询:ImageButton悬停缩放/加边框及子窗口悬停显边框
ImGui交互效果实现方案
问题1:ImageButton悬停时的突出显示(尺寸放大/添加边框)
实现悬停动态放大尺寸
ImGui是即时模式GUI,每帧都会重新渲染,可通过变量动态控制按钮尺寸,实现悬停时放大效果:
ImVec2 btnBaseSize = {40.0f, 40.0f}; ImVec2 btnHoverSize = {45.0f, 45.0f}; ImVec2 currentSize = btnBaseSize; // 预判悬停状态,避免尺寸变化延迟一帧 ImVec2 btnPos = ImGui::GetCursorScreenPos(); if (ImGui::IsMouseHoveringRect(btnPos, ImVec2(btnPos.x + btnBaseSize.x, btnPos.y + btnBaseSize.y))) { currentSize = btnHoverSize; } bool btn1 = ImGui::ImageButton((void*)(intptr_t)my_image_texture, currentSize); if (btn1) counter++; ImGui::SameLine(); ImGui::Text("counter = %d", counter);
如果不在意一帧延迟,也可以在绘制按钮后判断悬停,更新下帧尺寸:
ImVec2 currentSize = {40.0f, 40.0f}; bool btn1 = ImGui::ImageButton((void*)(intptr_t)my_image_texture, currentSize); if (ImGui::IsItemHovered()) currentSize = {45.0f, 45.0f}; else currentSize = {40.0f, 40.0f}; if (btn1) counter++; ImGui::SameLine(); ImGui::Text("counter = %d", counter);
实现悬停时添加边框(不修改尺寸)
若无法调整按钮尺寸,直接用ImGui绘图列表在按钮周围绘制边框:
bool btn1 = ImGui::ImageButton((void*)(intptr_t)my_image_texture, {40.0f,40.0f}); if (ImGui::IsItemHovered()) { ImDrawList* drawList = ImGui::GetWindowDrawList(); ImVec2 rectMin = ImGui::GetItemRectMin(); ImVec2 rectMax = ImGui::GetItemRectMax(); // 红色边框,线宽2px,可按需调整颜色和宽度 drawList->AddRect(rectMin, rectMax, IM_COL32(255, 0, 0, 255), 0.0f, 0, 2.0f); } if (btn1) counter++; ImGui::SameLine(); ImGui::Text("counter = %d", counter);
问题2:子窗口悬停时显示边框
方案1:动态控制BeginChild的border参数
先计算子窗口区域,判断是否被鼠标悬停,再动态设置BeginChild的border参数:
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, Dp2Px(5.0f)); ImVec2 childSize = ImVec2(Dp2Px(85), Dp2Px(48)); ImVec2 childPos = ImGui::GetCursorScreenPos(); bool isChildHovered = ImGui::IsMouseHoveringRect(childPos, ImVec2(childPos.x + childSize.x, childPos.y + childSize.y)); // 悬停时开启边框,否则关闭 ImGui::BeginChild(childId.c_str(), childSize, isChildHovered, window_flags); isClicked = ImGui::ImageButton((void*)(intptr_t)icons[i], ImVec2(45, 30)); ImGui::EndChild(); ImGui::PopStyleVar();
方案2:手动绘制边框
若不想修改BeginChild的border参数,可在子窗口绘制完成后,用绘图列表手动添加边框:
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, Dp2Px(5.0f)); ImGui::BeginChild(childId.c_str(), ImVec2(Dp2Px(85), Dp2Px(48)), false, window_flags); isClicked = ImGui::ImageButton((void*)(intptr_t)icons[i], ImVec2(45, 30)); ImGui::EndChild(); ImGui::PopStyleVar(); // EndChild后,IsItemHovered指向该子窗口 if (ImGui::IsItemHovered()) { ImDrawList* drawList = ImGui::GetWindowDrawList(); ImVec2 rectMin = ImGui::GetItemRectMin(); ImVec2 rectMax = ImGui::GetItemRectMax(); // 使用主题边框颜色,圆角与子窗口一致,线宽1px drawList->AddRect(rectMin, rectMax, ImGui::GetColorU32(ImGuiCol_Border), Dp2Px(5.0f), 0, 1.0f); }
内容的提问来源于stack exchange,提问作者Gagan karanth
相关产品推荐
相关产品推荐

