Skip to content

Clipper vs Table flickering #8488

@ozlb

Description

@ozlb

Version/Branch of Dear ImGui:

Version v1.91.8, released

Back-ends:

imgui_impl_glfw.cpp + imgui_impl_opengl2.cpp

Compiler, OS:

Windows 11 + MSVC 2022, Linux Debian + GCC

Full config/build information:

Dear ImGui 1.91.8 (19180)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=201103
define: __linux__
define: __GNUC__=12
--------------------------------
io.BackendPlatformName: imgui_impl_glfw
io.BackendRendererName: imgui_impl_opengl2
io.ConfigFlags: 0x00000003
 NavEnableKeyboard
 NavEnableGamepad
io.ConfigNavCaptureKeyboard
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x00000006
 HasMouseCursors
 HasSetMousePos
--------------------------------
io.Fonts: 1 fonts, Flags: 0x00000000, TexSize: 512,64
io.DisplaySize: 1280.00,720.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,3.00
style.FrameRounding: 0.00
style.FrameBorderSize: 0.00
style.ItemSpacing: 8.00,4.00
style.ItemInnerSpacing: 4.00,4.00

Minimal, Complete and Verifiable Example code:

This example will reproduce the issue of table "flickering" when using clipper.

{
    ImGui::SetNextWindowPos(ImVec2(374, 0), ImGuiCond_FirstUseEver);
    ImGui::SetNextWindowSize(ImVec2(541, 423), ImGuiCond_Once);
    if (ImGui::Begin("debug")) {
        const ImGuiTableFlags objectContentFlags = ImGuiTableFlags_NoSavedSettings  //peristency (save in ini file the table layout and setting
            | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY //scroll
            | ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_NoBordersInBody  //borders
            | ImGuiTableFlags_RowBg  //background color (alternated)
            | ImGuiTableFlags_Hideable
            | ImGuiTableFlags_SizingFixedFit;
        static bool useClipper = true;
        if (ImGui::BeginTable("objectContent", 3, objectContentFlags, ImVec2(0, -25)))
        {
            ImGui::TableSetupScrollFreeze(1, 1);
            ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHide);
            ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_None);
            ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_NoHide);
            ImGui::TableHeadersRow();
			const int K_Rows_Cnt = 100;
            struct MyTableContent
            {
                static void Fill(int start, int end) {
                    for (int i = start; i < end; i++) {
                        ImGui::TableNextRow();
                        ImGui::TableNextColumn();
                        //COLUMN [NAME]
                        ImGui::Text(((i % 20) == 0 ? "ITEM_LONG_NAME_%d" : "ITEM_%d"), i);
                        //COLUMN [TYPE]
                        ImGui::TableNextColumn();
                        ImGui::Text("%s", (i % 20) == 0 ? "string" : "number");
                        //COLUMN [VALUE]
                        ImGui::TableNextColumn();
                        if ((i % 20) == 0)
                            ImGui::Text("%s", "'long description                             '");
                        else
                            ImGui::Text("%d", i);
                    }
                }
            };
            if (useClipper) {
                ImGuiListClipper clipper;
                clipper.Begin(K_Rows_Cnt);
                while (clipper.Step())
                    MyTableContent::Fill(clipper.DisplayStart, clipper.DisplayEnd);
            }
            else
                MyTableContent::Fill(0, K_Rows_Cnt);
            ImGui::EndTable();
        }
        ImGui::Checkbox("use clipper", &useClipper);
    }
    ImGui::End();

}

Here below the clipper continuously recalculate amount of visible rows due to scrollbar that change the amount of available region.

[03240] Clipper: Begin(100,-1.00) in 'debug/objectContent_4108DFE8'
[03240] Clipper: Step(): display 0 to 1.
[03240] Clipper: Step(): computed ItemsHeight: 17.00.
[03240] Clipper: Step(): display 1 to 21.
[03240] Clipper: Step(): End.
[03240] Clipper: End() in 'debug/objectContent_4108DFE8'
[03241] Clipper: Begin(100,-1.00) in 'debug/objectContent_4108DFE8'
[03241] Clipper: Step(): display 0 to 1.
[03241] Clipper: Step(): computed ItemsHeight: 17.00.
[03241] Clipper: Step(): display 1 to 21.
[03241] Clipper: Step(): End.
[03241] Clipper: End() in 'debug/objectContent_4108DFE8'
[03242] Clipper: Begin(100,-1.00) in 'debug/objectContent_4108DFE8'
[03242] Clipper: Step(): display 0 to 1.
[03242] Clipper: Step(): computed ItemsHeight: 17.00.
[03242] Clipper: Step(): display 1 to 20.
[03242] Clipper: Step(): End.
[03242] Clipper: End() in 'debug/objectContent_4108DFE8'
[03243] Clipper: Begin(100,-1.00) in 'debug/objectContent_4108DFE8'
[03243] Clipper: Step(): display 0 to 1.
[03243] Clipper: Step(): computed ItemsHeight: 17.00.
[03243] Clipper: Step(): display 1 to 20.
[03243] Clipper: Step(): End.
[03243] Clipper: End() in 'debug/objectContent_4108DFE8'
[03244] Clipper: Begin(100,-1.00) in 'debug/objectContent_4108DFE8'
[03244] Clipper: Step(): display 0 to 1.
[03244] Clipper: Step(): computed ItemsHeight: 17.00.
[03244] Clipper: Step(): display 1 to 21.
[03244] Clipper: Step(): End.
[03244] Clipper: End() in 'debug/objectContent_4108DFE8'
[03245] Clipper: Begin(100,-1.00) in 'debug/objectContent_4108DFE8'
[03245] Clipper: Step(): display 0 to 1.
[03245] Clipper: Step(): computed ItemsHeight: 17.00.
[03245] Clipper: Step(): display 1 to 21.
[03245] Clipper: Step(): End.
[03245] Clipper: End() in 'debug/objectContent_4108DFE8'
[03246] Clipper: Begin(100,-1.00) in 'debug/objectContent_4108DFE8'
[03246] Clipper: Step(): display 0 to 1.
[03246] Clipper: Step(): computed ItemsHeight: 17.00.
[03246] Clipper: Step(): display 1 to 20.
[03246] Clipper: Step(): End.
[03246] Clipper: End() in 'debug/objectContent_4108DFE8'

Screenshots/Video:

Image
Flickering effect is filtered by screen-capture, it's with much higher frequency in reality.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions