1、组件的ID
只要是需要和使用者交互的组件,每一个组件都需要有一个ID,但是想Text这种组件可以不需要ID,但是想Button这种组件就需要一个ID。
Button("OK"); // Label = "OK", ID = hash of (..., "OK")
Button("Cancel"); // Label = "Cancel", ID = hash of (..., "Cancel")
ID就是创建的时候里面的参数。“OK”/“Cancel”。
2、创建的ID冲突了,应该怎么解决
①创建两个窗口:
Begin("MyWindow");
Button("OK"); // Label = "OK", ID = hash of ("MyWindow", "OK")
End();
Begin("MyOtherWindow");
Button("OK"); // Label = "OK", ID = hash of ("MyOtherWindow", "OK")
End();
②在ID里面使用补码的方式传给imgui,但是不给操作者显示
注意:这里是两个'#'号,使用两个#的时候,“#”前面的字符串就是当前组件的标签,也就是显示的字符,然后ID就是整个字符串,整个时候标签是可以一样的。
Begin("MyWindow");
Button("Play"); // Label = "Play", ID = hash of ("MyWindow", "Play")
Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1")
// Different from above
Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2")
// Different from above
End();
但是当你使用的三个“#”的时候:
整个时候,标签还是“#”前面的字符串,但是ID就不是整个字符串了,而是“#”以及“#”后面的字符串,这个时候组件的ID是不能重复的,一旦重复的话,第二个声明的组件是没有办法响应你的调用的。
Button("Hello###ID"); // Label = "Hello", ID = hash of (..., "###ID")
Button("World###ID"); // Label = "World", ID = hash of (..., "###ID") // Same as above, even though the label looks different
3、使用PushID/PopID来避免ID冲突
Begin("Window")
for (int i = 0; i < 5; i++)
{
ImGui::PushID(i); // 将循环计数作为ID
ImGui::Button("Go"); // Label = "Go", ID = hash of ("Window", i, "Go")
ImGui::PopID();
}
End();
imgui使用一个ID栈,只要栈里面有ID,那么接下来创建组件的时候,ID的组件就会从栈里面拿出来,并赋上去。
Tip:一个ID入栈就要对应一个ID出栈,否则程序就会出错
文档里面还给出了另外两种入ID栈的类型:
for (int i = 0; i < 100; i++)
{
MyObject* obj = Objects[i];
PushID(obj);
Button("Click"); // Label = "Click", ID = hash of ("Window", obj pointer, "Click")
PopID();
}
for (int i = 0; i < 100; i++)
{
MyObject* obj = Objects[i];
PushID(obj->Name);
Button("Click"); // Label = "Click", ID = hash of ("Window", obj->Name, "Click")
PopID();
}
说明了ID栈里面,不仅仅可以之存放int值,自己的类类型也是可以当做组件的ID的。
4、使用TreeNode创建节点的时候,会隐式的帮我们调用一次PushID
if (ImGui::TreeNode("TreeNode"))
{
ImGui::Button("TreeButton"); // Label = "TreeButton", ID = hash of (..., "TreeNode", "TreeButton")
ImGui::TreePop();
}
使用完成之后,也一定要Pop一下,不然当你点击TreeNode的时候,还是会出现问题