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

如何在ImGui中创建表格并实现整体绕中心旋转?

在ImGui中实现旋转表格的方案

核心思路

ImGui本身没有直接支持UI元素旋转的API,但可以通过修改ImDrawList的渲染变换矩阵实现表格整体旋转。关键是围绕表格中心构建旋转变换,绘制表格时应用该变换,绘制完成后恢复原变换。

具体实现步骤

1. 提前计算表格的尺寸与中心位置

首先需要确定表格的整体尺寸,才能找到旋转中心。如果表格高度是动态计算的,可预计算总高度:

// 计算表格总高度
float totalTableHeight = 0.0f;
for (int row = 0; row < globalRowCount; row++) {
    totalTableHeight += row_heights[row] * dpi;
}
// 获取表格左上角的屏幕坐标
ImVec2 tablePos = ImGui::GetCursorScreenPos();
// 计算表格中心坐标
ImVec2 tableCenter = ImVec2(
    tablePos.x + tableWidth / 2.0f,
    tablePos.y + totalTableHeight / 2.0f
);

2. 应用旋转变换矩阵

在绘制表格前,向ImGui的绘图列表中推入旋转变换,构建围绕中心旋转的矩阵:

ImGuiWindow* window = ImGui::GetCurrentWindow();
ImDrawList* drawList = window->DrawList;

// 旋转角度(弧度制,示例为30度,可替换为自定义角度)
float rotationAngle = ImGui::DegToRad(30.0f);

// 构建变换矩阵:平移到原点→旋转→平移回中心
ImMatrix4x4 transform = ImMatrix4x4::Identity();
transform.Translate(-tableCenter.x, -tableCenter.y, 0.0f);
transform.RotateZ(rotationAngle);
transform.Translate(tableCenter.x, tableCenter.y, 0.0f);

// 推入变换
drawList->PushTransform(transform);

3. 处理鼠标交互匹配问题

旋转后的表格会出现鼠标点击位置与UI元素不匹配的情况,需要临时转换鼠标坐标:

// 保存原始鼠标位置
ImVec2 originalMousePos = ImGui::GetMousePos();
// 反向转换鼠标位置到旋转后的坐标系
ImVec2 transformedMousePos = transform.Inverted().TransformPoint(originalMousePos);
// 临时替换鼠标位置
ImGui::SetMousePos(transformedMousePos);

4. 绘制表格(保留原有代码)

将你已有的表格绘制代码放在变换生效期间:

ImGui::BeginTable(tableId.c_str(), globalColumnCount, tableFlags, ImVec2(tableWidth, totalTableHeight));

// 你的原有列设置代码
for (int col = 0; col < globalColumnCount; col++)
{
    ImGui::TableSetupColumn(headers[col].c_str(), ImGuiTableColumnFlags_WidthStretch, 0.0f, col / static_cast<float>(globalColumnCount));
}

// 你的原有行绘制代码
for (int row = 0; row < globalRowCount; row++)
{
    ImGui::TableNextRow();
    float cellRowHeight = row_heights[row] * dpi;
    ImGui::SetCursorPosY(ImGui::GetCursorPosY() + cellRowHeight);

    if (row < globalheadercount) {
        for (int col = 0; col < globalColumnCount; col++) {
            ImGui::TableNextColumn();
            ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImVec4(0.0f, 0.0f, 0.0f, 0.0f))); 
            ImGui::Text("");
        }
    }
    else if (row >= globalheadercount + globalBodyCount) {
        for (int col = 0; col < globalColumnCount; col++) {
            ImGui::TableNextColumn();
            ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImVec4(0.0f, 0.0f, 0.0f, 0.0f)));
            ImGui::Text("");
        }
    } else {
        ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0, 0, 0, 0));
        ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0, 0, 0, 1));    

        for (int col = 0; col < globalColumnCount; col++) {
            ImGui::TableNextColumn();
            std::string inputID = "###Input_" + elem_id + "_" + std::to_string(row) + "_" + std::to_string(col);
            ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0, 0, 0, 1));
            ImGui::InputText(inputID.c_str(), &cellTexts[tableIndex][row * globalColumnCount + col]);
            ImGui::PopStyleColor();
        }
        ImGui::PopStyleColor(2);
    }
}

ImGui::EndTable();

5. 恢复原状态

表格绘制完成后,恢复鼠标位置与渲染变换:

// 恢复原始鼠标位置
ImGui::SetMousePos(originalMousePos);
// 弹出变换,避免影响后续UI
drawList->PopTransform();

注意事项

  • 确保使用的ImGui版本支持ImDrawList::PushTransform和ImMatrix4x4(ImGui 1.89及以上版本已支持)。
  • 如果表格尺寸随内容动态变化,需每次绘制时重新计算尺寸与中心。
  • 旋转角度需使用弧度制,可通过ImGui::DegToRad()将角度转换为弧度。

内容的提问来源于stack exchange,提问作者Kazi Ruvef

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 13:30:06