Slick Forums
http://slick.ninjacave.com/forum/

[Solved]TWL RootPane trying to add the same child widget?
http://slick.ninjacave.com/forum/viewtopic.php?f=18&t=6664
Page 1 of 1

Author:  mcminnra [ Fri Aug 02, 2013 7:41 pm ]
Post subject:  [Solved]TWL RootPane trying to add the same child widget?

Alrighty

So, I'm trying to create a basic RPG with a persistent inventory that is drawn on every GameState.
I unfortunately get this error.

Code:
Fri Aug 02 13:50:42 EDT 2013 ERROR:child widget already in tree
java.lang.IllegalArgumentException: child widget already in tree
   at de.matthiasmann.twl.Widget.insertChild(Widget.java:1244)
   at de.matthiasmann.twl.Widget.add(Widget.java:1222)
   at org.mcminn.arcanium.inventory.InventoryPanel.<init>(InventoryPanel.java:37)
   at org.mcminn.arcanium.states.World.createRootPane(World.java:65)
   at TWLSlick.BasicTWLGameState.getRootPane(BasicTWLGameState.java:61)
   at TWLSlick.BasicTWLGameState.enter(BasicTWLGameState.java:80)
   at org.newdawn.slick.state.StateBasedGame.update(StateBasedGame.java:248)
   at org.newdawn.slick.GameContainer.updateAndRender(GameContainer.java:663)
   at org.newdawn.slick.AppGameContainer.gameLoop(AppGameContainer.java:411)
   at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:321)
   at org.mcminn.arcanium.Game.main(Game.java:56)


I'm using the demo inventory for the TWL homepage just to serve as a proof of concept until I can get around to writing my own.
the error points to this line
Code:
add(inventory.getItem(i));//this is inventory child widget issue

in this file.
Code:
package org.mcminn.arcanium.inventory;

import de.matthiasmann.twl.Event;
import de.matthiasmann.twl.ThemeInfo;
import de.matthiasmann.twl.Widget;

public class InventoryPanel extends Widget {
   
    private int numSlotsX;
    private int numSlotsY;
   
    private Inventory inventory;
   
    private int slotSpacing;

    private ItemSlot dragSlot;
    private ItemSlot dropSlot;
   
    public InventoryPanel(int numSlotsX, int numSlotsY, Inventory inventory) {
        this.numSlotsX = numSlotsX;
        this.numSlotsY = numSlotsY;
        this.inventory = inventory;
        ItemSlot.DragListener listener = new ItemSlot.DragListener() {
            public void dragStarted(ItemSlot slot, Event evt) {
                InventoryPanel.this.dragStarted(slot, evt);
            }
            public void dragging(ItemSlot slot, Event evt) {
                InventoryPanel.this.dragging(slot, evt);
            }
            public void dragStopped(ItemSlot slot, Event evt) {
                InventoryPanel.this.dragStopped(slot, evt);
            }
        };
       
        for(int i=0 ; i<inventory.getInventorySlots().length ; i++) {
           inventory.getItem(i).setListener(listener);
           add(inventory.getItem(i));//this is inventory child widget issue
        }
       
        inventory.setDefaultInventory();
    }

    @Override
    public int getPreferredInnerWidth() {
        return (inventory.getItem(0).getPreferredWidth() + slotSpacing)*numSlotsX - slotSpacing;
    }

    @Override
    public int getPreferredInnerHeight() {
        return (inventory.getItem(0).getPreferredHeight() + slotSpacing)*numSlotsY - slotSpacing;
    }

    @Override
    protected void layout() {
       /* measures size of first icon
        int slotWidth  = inventory.getItem(0).getPreferredWidth();
        int slotHeight = inventory.getItem(0).getPreferredHeight();
        */
       int slotWidth  = 32;
        int slotHeight = 35;
       
       
        for(int row=0,y=getInnerY(),i=0 ; row<numSlotsY ; row++) {
            for(int col=0,x=getInnerX() ; col<numSlotsX ; col++,i++) {
               inventory.getItem(i).adjustSize();
               inventory.getItem(i).setPosition(x, y);
                x += slotWidth + slotSpacing;
            }
            y += slotHeight + slotSpacing;
        }
    }

    @Override
    protected void applyTheme(ThemeInfo themeInfo) {
        super.applyTheme(themeInfo);
        slotSpacing = themeInfo.getParameter("slotSpacing", 9);
    }
    void dragStarted(ItemSlot slot, Event evt) {
        if(slot.getItem() != null) {
            dragSlot = slot;
            dragging(slot, evt);
        }
    }
   
    void dragging(ItemSlot slot, Event evt) {
        if(dragSlot != null) {
            Widget w = getWidgetAt(evt.getMouseX(), evt.getMouseY());
            if(w instanceof ItemSlot) {
                setDropSlot((ItemSlot)w);
            } else {
                setDropSlot(null);
            }
        }
    }
   
    void dragStopped(ItemSlot slot, Event evt) {
        if(dragSlot != null) {
            dragging(slot, evt);
            if(dropSlot != null && dropSlot.canDrop() && dropSlot != dragSlot) {
                dropSlot.setItem(dragSlot.getItem());
                dragSlot.setItem(null);
            }
            setDropSlot(null);
            dragSlot = null;
        }
    }

    private void setDropSlot(ItemSlot slot) {
        if(slot != dropSlot) {
            if(dropSlot != null) {
                dropSlot.setDropState(false, false);
            }
            dropSlot = slot;
            if(dropSlot != null) {
                dropSlot.setDropState(true, dropSlot == dragSlot || dropSlot.canDrop());
            }
        }
    }
   
}



I wrote my own class to handle changing and processing the inventory

Code:
package org.mcminn.arcanium.inventory;

public class Inventory {
   
   private ItemSlot[] inventory = new ItemSlot[56]; // 56 - Number of Slots
   
   public Inventory(){
      for(int i=0 ; i<inventory.length ; i++) {
            inventory[i] = new ItemSlot();
        }
   }
   
   protected void setDefaultInventory(){
      inventory[0].setItem("red");
      inventory[1].setItem("green");
      inventory[2].setItem("blue");
      inventory[3].setItem("yellow");
   }
   public void addItem(String Item){
      
   }
   
   public ItemSlot getItem(int pos){
      return inventory[pos];
   }
   public ItemSlot[] getInventorySlots(){
      return inventory;
   }
   public Inventory getInventory(){
      return this;
   }
}


and initialize it is a static class in the game

Code:
static Inventory inventory;
   
   public Game(String title){
      super(title);
      
      //player inventory
      inventory = new Inventory();
      
      this.addState(new Menu(menu, this));
      this.addState(new ThroneRoom(throneRoom, inventory));
      this.addState(new World(world, inventory));
   }


and then pass it to each game state to render.

Code:
public ThroneRoom(int state, Inventory inventory) {
      this.inventory = inventory;
   }

   @Override
   protected RootPane createRootPane() {
      rp = super.createRootPane();
      rp.setTheme("");

      testMini = new Button("MINIMAP");
      testMini.setTheme("button");
      testChat = new Button("CHAT");
      testChat.setTheme("button");
      
      //inventory
      inventoryPanel = new InventoryPanel(6, 8, inventory);
      inventoryFrame = new ResizableFrame();
      inventoryFrame.setTitle("Inventory");
      inventoryFrame.setResizableAxis(ResizableFrame.ResizableAxis.NONE);
      inventoryFrame.add(inventoryPanel);
      
        rp.add(inventoryFrame);
      rp.add(testMini);
      rp.add(testChat);

      return rp;
   }

   @Override
   protected void layoutRootPane() {
      inventoryFrame.setPosition(768, 384);
      inventoryFrame.setSize(256, 384);
       testMini.setPosition(768, 0);
       testMini.setSize(256, 384);
       testChat.setPosition(0, 576);
       testChat.setSize(768, 194);
   }


It works fine when entering the first gamestate, but when i move to a different gamestate. I get the error.
I've been staring at this problem for about 5 hours, any help would be greatly appreciated.

I can provide full source code if need be.

Author:  mcminnra [ Sat Aug 03, 2013 10:04 pm ]
Post subject:  Re: TWL RootPane trying to add the same child widget?

Never mind, solved my own problem!

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/