You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 09:55:24