Wir haben festgestellt, dass Euer Browser keine Cookies akzeptiert. Bitte erlaubt die Verwendung von Cookies in den Optionen Eures Browsers, um eine optimale Funktion dieser Webseite zu gewährleisten.
Ergebnis 1 bis 3 von 3
  1. #1
    Registriert seit
    25.03.2007
    Beiträge
    1.212

    ListBox:Sort() causes index errors

    Using the ListBox:Sort() method causes issues with the listbox's internal indexes for its elements so that other methods like RemoveItemAt() and ClearItems() no longer function properly. I first noticed this when, after sorting a listbox control, I called ClearItems and would sometimes have items still displayed in the listbox even though GetItemCount() returned 0 and the items were no longer controllable. I did a bit of research and realized that even using RemoveItemAt() would leave ghost items because it seemed to be leaving a gap in the internal list of indexes so that calling GetItem() for that index returned nil and one of the legitimate items became unaccessible.

    An example of this can be seen with the following code segments:
    Code:
    local index;
    local items={"duidei","dfaho","oubo","avoaleb","coabfe","dubso","oaiubd","aldfhu","fsouhde"}
    itemList=Turbine.UI.ListBox()
    for index=1,#items do
     local tmpItem=Turbine.UI.Label()
     local tmpVal=items[index]
     tmpItem:SetParent(itemList)
     tmpItem:SetSize(100,20)
     tmpItem:SetText("val="..tostring(tmpVal).." orig_index="..tostring(index) )
     tmpItem.index=index
     itemList:AddItem(tmpItem)
    end
    Turbine.Shell.WriteLine("before removal")
    for index=1,itemList:GetItemCount() do
      if itemList:GetItem(index) == nil then
         Turbine.Shell.WriteLine("item at:"..tostring(index).." is nil")
      else
         Turbine.Shell.WriteLine("item at:"..tostring(index).." orig_index="..tostring(itemList:GetItem(index).index))
      end
    end
    itemList:RemoveItemAt(5)
    Turbine.Shell.WriteLine("after removal")
    for index=1,itemList:GetItemCount() do
      if itemList:GetItem(index) == nil then
         Turbine.Shell.WriteLine("item at:"..tostring(index).." is nil")
      else
         Turbine.Shell.WriteLine("item at:"..tostring(index).." orig_index="..tostring(itemList:GetItem(index).index))
      end
    end
    Using this code works correctly, the entry at index 5 is removed.
    But, by adding a sort and removing the item at index 5:
    Code:
    local index;
    local items={"duidei","dfaho","oubo","avoaleb","coabfe","dubso","oaiubd","aldfhu","fsouhde"}
    itemList=Turbine.UI.ListBox()
    for index=1,#items do
     local tmpItem=Turbine.UI.Label()
     local tmpVal=items[index]
     tmpItem:SetParent(itemList)
     tmpItem:SetSize(100,20)
     tmpItem:SetText("val="..tostring(tmpVal).." orig_index="..tostring(index) )
     tmpItem.index=index
     itemList:AddItem(tmpItem)
    end
    Turbine.Shell.WriteLine("before sort")
    for index=1,itemList:GetItemCount() do
      if itemList:GetItem(index) == nil then
         Turbine.Shell.WriteLine("item at:"..tostring(index).." is nil")
      else
         Turbine.Shell.WriteLine("item at:"..tostring(index).." orig_index="..tostring(itemList:GetItem(index).index))
      end
    end
    itemList:Sort(function(elem1,elem2) if elem1:GetText()<elem2:GetText() then return true end end)
    Turbine.Shell.WriteLine("before removal")
    for index=1,itemList:GetItemCount() do
      if itemList:GetItem(index) == nil then
         Turbine.Shell.WriteLine("item at:"..tostring(index).." is nil")
      else
         Turbine.Shell.WriteLine("item at:"..tostring(index).." orig_index="..tostring(itemList:GetItem(index).index))
      end
    end
    itemList:RemoveItemAt(5)
    Turbine.Shell.WriteLine("after removal")
    for index=1,itemList:GetItemCount() do
      if itemList:GetItem(index) == nil then
         Turbine.Shell.WriteLine("item at:"..tostring(index).." is nil")
      else
         Turbine.Shell.WriteLine("item at:"..tostring(index).." orig_index="..tostring(itemList:GetItem(index).index))
      end
    end
    we get a nil item at index 3 which contained the entry that was ORIGINALLY (before the sort) at index 5. Somehow, the sort is not updating the internal index of the entry so the wrong entry is getting removed and is leaving an inaccessible entry.

  2. #2
    Registriert seit
    12.05.2009
    Beiträge
    176
    Zitat Zitat von Garan Beitrag anzeigen
    Using the ListBox:Sort() method causes issues with the listbox's internal indexes for its elements so that other methods like RemoveItemAt() and ClearItems() no longer function properly. I first noticed this when, after sorting a listbox control, I called ClearItems and would sometimes have items still displayed in the listbox even though GetItemCount() returned 0 and the items were no longer controllable. I did a bit of research and realized that even using RemoveItemAt() would leave ghost items because it seemed to be leaving a gap in the internal list of indexes so that calling GetItem() for that index returned nil and one of the legitimate items became unaccessible.

    An example of this can be seen with the following code segments:
    Code:
    local index;
    local items={"duidei","dfaho","oubo","avoaleb","coabfe","dubso","oaiubd","aldfhu","fsouhde"}
    itemList=Turbine.UI.ListBox()
    for index=1,#items do
     local tmpItem=Turbine.UI.Label()
     local tmpVal=items[index]
     tmpItem:SetParent(itemList)
     tmpItem:SetSize(100,20)
     tmpItem:SetText("val="..tostring(tmpVal).." orig_index="..tostring(index) )
     tmpItem.index=index
     itemList:AddItem(tmpItem)
    end
    Turbine.Shell.WriteLine("before removal")
    for index=1,itemList:GetItemCount() do
      if itemList:GetItem(index) == nil then
         Turbine.Shell.WriteLine("item at:"..tostring(index).." is nil")
      else
         Turbine.Shell.WriteLine("item at:"..tostring(index).." orig_index="..tostring(itemList:GetItem(index).index))
      end
    end
    itemList:RemoveItemAt(5)
    Turbine.Shell.WriteLine("after removal")
    for index=1,itemList:GetItemCount() do
      if itemList:GetItem(index) == nil then
         Turbine.Shell.WriteLine("item at:"..tostring(index).." is nil")
      else
         Turbine.Shell.WriteLine("item at:"..tostring(index).." orig_index="..tostring(itemList:GetItem(index).index))
      end
    end
    Using this code works correctly, the entry at index 5 is removed.
    But, by adding a sort and removing the item at index 5:
    Code:
    local index;
    local items={"duidei","dfaho","oubo","avoaleb","coabfe","dubso","oaiubd","aldfhu","fsouhde"}
    itemList=Turbine.UI.ListBox()
    for index=1,#items do
     local tmpItem=Turbine.UI.Label()
     local tmpVal=items[index]
     tmpItem:SetParent(itemList)
     tmpItem:SetSize(100,20)
     tmpItem:SetText("val="..tostring(tmpVal).." orig_index="..tostring(index) )
     tmpItem.index=index
     itemList:AddItem(tmpItem)
    end
    Turbine.Shell.WriteLine("before sort")
    for index=1,itemList:GetItemCount() do
      if itemList:GetItem(index) == nil then
         Turbine.Shell.WriteLine("item at:"..tostring(index).." is nil")
      else
         Turbine.Shell.WriteLine("item at:"..tostring(index).." orig_index="..tostring(itemList:GetItem(index).index))
      end
    end
    itemList:Sort(function(elem1,elem2) if elem1:GetText()<elem2:GetText() then return true end end)
    Turbine.Shell.WriteLine("before removal")
    for index=1,itemList:GetItemCount() do
      if itemList:GetItem(index) == nil then
         Turbine.Shell.WriteLine("item at:"..tostring(index).." is nil")
      else
         Turbine.Shell.WriteLine("item at:"..tostring(index).." orig_index="..tostring(itemList:GetItem(index).index))
      end
    end
    itemList:RemoveItemAt(5)
    Turbine.Shell.WriteLine("after removal")
    for index=1,itemList:GetItemCount() do
      if itemList:GetItem(index) == nil then
         Turbine.Shell.WriteLine("item at:"..tostring(index).." is nil")
      else
         Turbine.Shell.WriteLine("item at:"..tostring(index).." orig_index="..tostring(itemList:GetItem(index).index))
      end
    end
    we get a nil item at index 3 which contained the entry that was ORIGINALLY (before the sort) at index 5. Somehow, the sort is not updating the internal index of the entry so the wrong entry is getting removed and is leaving an inaccessible entry.
    Just checked in a change that should hopefully fix this.

  3. #3
    Registriert seit
    21.06.2011
    Beiträge
    700
    Thurallor, Warden of Landroval

 

 

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Diese Formular-Sitzung ist abgelaufen. Du musst die Seite neu laden.

Neu laden