5 Replies Latest reply on Jan 3, 2008 9:07 AM by peterent

    Adding vector shapes to GUI

    migthegreek
      Hi, I'm new to Flex but I come from Flash and have a good knowledge of ActionScript. I'm just not sure how to apply it at the moment.

      I'm building a GUI and I just want to add a vector rectangle or anything to a panel. I tried putting this in a Script tag but I have no idea how I add the child to the Panel in the MXML (if that is even possible).

      import flash.display.*;
      var square:Sprite = new Sprite();
      square.graphics.lineStyle(1, 0);
      square.graphics.beginFill(0xFF0000);
      square.graphics.drawRect(500, 100, 100, 100);
      square.graphics.endFill();
      addChild(square);


      I just get told "Access of undefined property square" on all the square lines, or if I use this.addChild(square) I don't get told that, but instead I get told I can't use this in a static method (how is it a static method?).

      It's kind of confusing without an apparent root level at which the code starts. I must be missing something.
        • 1. Re: Adding vector shapes to GUI
          peterent Level 2
          The code you wrote needs to be in a function that gets called by the Flex framework. It looks like you put the code inside of a class, but not inside of a function.

          In the Flex framework you should put your code in 2 places:

          First, make sure your class extends a Flex framework class, like UIComponent or Panel. Then you should override the createChildren() function where you can create your Sprite:

          override protected function createChildren() : void
          {
          super.createChildren(); // allow the super class function to run
          // create the Sprite
          // use addChild() to put it on the component's display list. See caveat below
          }

          Then you need to draw your graphics. If you are using a Flash construct, you can draw it when you create it, but that's not the best thing in Flex. Perhaps you will want to use a property or style on your class to determine the color, for example.

          Override the updateDisplayList() function and include your drawing code:

          override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ) : void
          {
          super.updateDisplayList( unscaledWidth, unscaledHeight );
          // draw here
          }

          The Flex framework calls updateDisplayList() when it is the time to put up the graphics. This includes sizing and positioning children, so it is also a good place to position your sprite.

          There is a caveat: If your class extends UIComponent (the basis of all Flex components), you can use Flash objects like Spite and Shape. But if you extend another class, like Panel, the addChild() function won't allow you to have a child that isn't an extension of UIComponent. That's because the "higher" classes in the Flex framework require their children to be true Flex components.

          So if you are extending Panel, don't create a Sprite. Just create a UIComponent and use it as you would a Sprite or a Shape.

          Take a moment to read up on the Flex framework functions such as createChildren(), commitProperties(), measure(), and updateDisplayList().
          • 2. Adding vector shapes to GUI
            migthegreek Level 1
            Hmm... I understand but I think perhaps I should explain more.

            I am building a quick test area for my own purposes, and the code I am writing is in my MXML file in a Script block (not in a class). I have no problems with OOP but I am wondering if it is possible to add arbitrary code to an MXML file which then dynamically creates ActionScript objects on the stage?

            To clarify what I mean, I have a Panel with a DataGrid inside. Next to the DataGrid I simply want to create a red square, let's say. Currently I am just using a Canvas object with a defined size and background colour of red. Is it possible to create the red square at runtime, with ActionScript that exists in the same MXML file, in a <mx:Script> block somewhere?
            • 3. Re: Adding vector shapes to GUI
              peterent Level 2
              I see. Try something like this in the <mx:Script> block:
              override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ) : void
              {
              super.updateDisplayList( unscaledWidth, unscaledHeight );
              var square:UIComponent = new UIComponent();
              square.graphics.lineStyle(1, 0);
              square.graphics.beginFill(0xFF0000);
              square.graphics.drawRect(500, 100, 100, 100);
              square.graphics.endFill();
              addChild(square);
              }

              You still have to get the Flex framework to invoke a function where you can render the graphics, even if you use an MXML file (which is turned into an ActionScript class file by the mxmlc compiler). If updateDisplayList is called often, you'll get multiple squares, so I would also override createChildren inside the same Script block and create the square child there and draw into it in updateDisplayList.
              • 4. Re: Adding vector shapes to GUI
                migthegreek Level 1
                Thanks Peter. I need a little more help. Where do I place this code (its Script block) in my MXML, and how do I call this function to add the child to a Panel object?

                Are Script blocks relative to where they are placed? i.e. Will the addChild() method therefore add the child to the MXML object where the Script block resides?
                • 5. Re: Adding vector shapes to GUI
                  peterent Level 2
                  I'm going to use dots to represent spaces as this forum doesn't preserve blanks:

                  <mx:Script>
                  <![CDATA[
                  import flash.display.*;
                  private var square:UIComponent;
                  override protected function createChildren() : void
                  {
                  ....super.createChildren();
                  ....square = new UIComponent();
                  ....addChild(square);
                  }

                  override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ) : void
                  {
                  ....super.updateDisplayList(unscaledWidth,unscaledHeight);
                  ....square.graphics.lineStyle(1,0);
                  ....// the rest of your drawing code here
                  ....square.endFill();
                  }
                  ]]>
                  </mx:Script>

                  That should give you a square in the Panel. If the Panel's layout="horizontal" and you also have a DataGrid, the square will be next to the DataGrid.

                  The placement of the Script block doesn't matter. The mxmlc compiler will extract the code in the block and put it into the generated ActionScript class that it makes from the mxml file.