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的時候,還是會出現問題