I have a custom Flex Toggleswitch component that changes the text values of the switch.
package skins
{
import spark.skins.mobile.ToggleSwitchSkin;
public class MyToggleSwitchSkin extends ToggleSwitchSkin
{
public function MyToggleSwitchSkin()
{
super();
selectedLabel="Serviceable";
unselectedLabel="Fault";
}
}
}
If I add the control using the MXML tag, it works fine. However, when I add the component using action script, it does not.
import skins.MyToggleSwitchSkin;
public function addToggle():void {
var myCustomToggle:MyToggleSwitchSkin = new MyToggleSwitchSkin();
hgroup.addElement(myCustomToggle);
}
The control dsiplays but will not activate.
Any ideas what I have missed?
Without seeing your MXML Code, it's tough to compare your two approaches, but I believe #al_Birdy addressed the problem. You've created a custom ToggleSwitchSkin; not a custom ToggleSwitch.
Modify your addToggle() method like this:
public function addToggle():void {
var myCustomToggle:MyToggleSwitch = new MyToggleSwitch();
myCustomToggle.setStyle('skinClass',skins.MyToggleSwitchSkin);
hgroup.addElement(myCustomToggle);
}
I suspect you'll have better luck.
Related
I am working in actionscript3, and since I'm self-taught, I think I've developed some bad habits, including coding on the timeline and using multiple scenes.
I am hoping to rectify this now that I'm working on a larger project.
Based on what I've read, linking multiple .fla files together is a better practice, each with their own document class. Is that correct?
If so, how do I load one .fla with its document class and then link that into the subsequent .fla file (instead of using scenes)? Or am I misinterpreting what was recommended?
Thanks!
There's no point to split your application in several loadable modules unless you have any of the following preconditions:
you have smart resource management to load and unload content
if you put everything into one file it gets just too big and hard to work with in design time or it takes far too long to compile
Regular AS3 alternative to working with scenes is creating/destroying content instances and using the main document class as their manager. You design content in the library and create behavior AS3 classes for them. Lets say, you have two content classes A and B. At the start the manager should show one of them and wait for the signal to show next one:
private var APage:A;
private var BPage:B;
gotoA();
function gotoA():void
{
if (BPage)
{
BPage.destroy();
removeChild(BPage);
BPage.removeEventListener(Event.CLOSE, gotoA);
}
APage = new A;
APage.addEventListener(Event.CLOSE, gotoB);
addChild(APage);
}
function gotoB():void
{
if (APage)
{
APage.destroy();
removeChild(APage);
APage.removeEventListener(Event.CLOSE, gotoB);
}
BPage = new B;
BPage.addEventListener(Event.CLOSE, gotoA);
addChild(BPage);
}
So, both A and B should have respective methods .destroy() that release used resources, unsubscribes methods from events, remove display objects, and so on, and they both should fire Event.CLOSE when they're done.
If you have many pages like that, you need to go for more algorithmic approach. For example, to create class BasicPage which will interact with manager and have the methods needed in all pages already declared:
package
{
import flash.display.Sprite;
class BasicPage extends Sprite
{
// A reference to the page manager instance.
public var Manager:PageManager;
public function destroy():void
{
while (numChildren > 0) removeChildAt(0);
Manager = null;
}
// Subclasses will have an access to this method to tell manager to show another page.
protected function showOtherPage(pageClass:Class):void
{
Manager.showPage(pageClass);
}
// A method that is called by manager when everything is ready.
// If page should take any actions on start it is a good idea to override this method.
public function startEngine():void
{
}
}
}
Then, example page A:
package
{
import flash.events.MouseEvent;
public class A extends BasicPage
{
// Lets say, class A in library have a designed button named Click.
public var Click:SimpleButton;
// We have things to undo here.
override public function destroy():void
{
Click.removeEventListener(MouseEvent.CLICK, onClick);
Click = null;
// Pass the destruction to superclass so it wraps its existence either.
super.destroy();
}
override public function startEngine():void
{
Click.addEventListener(MouseEvent.CLICK, onClick);
}
private function onClick(e:MouseEvent):void
{
// Lets use inherited method to show other page.
showOtherPage(B);
}
}
}
So, PageManager will be like:
package
{
public class PageManager extends Sprite
{
private var Page:BasicPage;
// constructor
function PageManager()
{
super();
showPage(A);
}
function showPage(pageClass:Class):void
{
if (Page)
{
Page.destroy();
removeChild(Page);
Page = null;
}
Page = new pageClass;
Page.Manager = this;
addChild(Page);
Page.startEngine();
}
}
}
This all could look scary at first, but it really isn't. PageManager will always have a current page, once there's a need to show another page, the current will be destroyed on a regular basis. Each page class will tend to its own content, which makes coding simpler, for you don't need to see the whole picture. If you need any persistent data, keep it in the PageManager so each page will have access to the data with no need for the pages to communicate with each other.
I would like to implement check boxes inside flash list control using Flash Pro CS6. I literally follow example provided by Adobe at Work with a CellRenderer. The only code in my .fla file is:
myList.setStyle("cellRenderer", CustomCellRenderer);
myList.addItem({label:"Burger -- $5.95"});
myList.addItem({label:"Fries -- $1.95"});
and the only code in the CustomCellRenderer.as file is (copy-paste from the Adobe example):
package
{
import fl.controls.CheckBox;
import fl.controls.listClasses.ICellRenderer;
import fl.controls.listClasses.ListData;
public class CustomCellRenderer extends CheckBox implements ICellRenderer {
private var _listData:ListData;
private var _data:Object;
public function CustomCellRenderer() {
}
public function set data(d:Object):void {
_data = d;
label = d.label;
}
public function get data():Object {
return _data;
}
public function set listData(ld:ListData):void {
_listData = ld;
}
public function get listData():ListData {
return _listData;
}
}
}
When I test movie I get the following error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at fl.controls::CheckBox/drawLayout()
at fl.controls::LabelButton/draw()
at fl.core::UIComponent/drawNow()
at fl.controls::List/drawList()
at fl.controls::List/draw()
at fl.core::UIComponent/callLaterDispatcher()
Any help would be greatly appreciated.
P.S. The author of similar question Display checkbox inside Flash List Control ? (Similar to item rendering in Flex) does not seem to have this problem - his problem is just in multiple selection functionality.
ANSWER (can not post answers for another 8 hour but eager to close the issue) Figured out myself: CheckBox component must be present in the library. Go to menu Window->Components-> Double click CheckBox. Check box will appear on the stage and in the library. Remove check box from the stage. Test movie.
Drag an instance of CheckBox component onto the stage then delete off the stage.
I have a class, and I'd like to make it available for use anywhere within a Flash project. Where should I put it? Ideally, it'd be in a separate ActionScript file.
If your ActionScript 3 project using classes, you can simply create global variable using public static like this :
//MyClass.as
package {
public class MyClass {
public static var myValue = 3;
}
}
//Arbitrary.as
package {
public class Arbitrary {
function Arbitrary():void {
trace(MyClass.myValue); //3
}
}
}
You in every project, follow these steps to enable.
Click ActionScript 3.0 Settings...
Click Source path folder icon, select a you want src folders.
You can use top level default package declaration.
package com.abc.globals
{
//Note here No Class Declaration
public var globalVars:String = "Global is horrible";
}
So that you can use without import statement and you can use access variable without class or instance.
It is like our trace("Hello Global").
globalVars will access from anywhere in application.
Lets's say you have 2 classes ToolBar and DrawingToolBar. ToolBar is to serve as a base class for various other toolbars, for various tools. ToolBar handles the basic 'toolbar-y' stuff like opening, closing, dragging, dropping, etc. The DrawingToolBar adds functionality that is specific to a particular tool - tool-specific buttons, etc.
public class ToolBar extends Sprite {
public var closeBtn:Sprite
public function ToolBar():void {
addChild(closeBtn)
closeBtn.addEventListener(MouseEvent.CLICK, closeBtn_onClick)
}
protected function closeBtn_onClick(e:Event):void {
close()
}
public function open():void {
// blah
}
public function close():void {
// blah
}
}
and:
public class DrawingToolBar extends ToolBar{
public var penBtn: Sprite
public var paintbrushBtn: Sprite
public var colorPicker: ColorPicker
public function DrawingToolBar():void {
super()
}
public function getColour():int {
return colorPicker.color;
}
}
Now, we also have another 2 classes - Tool and DrawingTool. Again, Tool is a base class for various tools (incl. DrawingTool). If I make a ToolBar member in Tool (typed as ToolBar), we can delegate common tasks, eg. when the Tool is enabled, it adds the ToolBar to the stage, etc. The DrawingTool can instantiate the ToolBar as a DrawingToolBar so the correct library asset is used (but the instance is still typed as ToolBar).
public class Tool {
public var toolBar:ToolBar
public function Tool():void {
initToolBar()
}
protected function initToolBar():void {
addChild(toolBar)
}
}
and:
public class DrawingTool extends Tool {
public function DrawingTool():void {
super()
}
override protected function initToolBar():void {
toolbar = new DrawingToolBar() // this is probably very naughty
super.initToolBar()
}
public function getColor():int {
return toolBar.getColor() // this fails because toolBar is type as ToolBar not DrawingToolBar
}
}
The problem comes when, in DrawingTool I want to call a method of DrawingToolBar. Because the toolbar is typed as ToolBar, I can't call methods of DrawingToolBar on it. What do I do?
cast it every time I want to call a method of DrawingToolBar?
create a member in DrawingTool (eg. var drawingToolBar: DrawingToolBar), instantiate that and then make toolBar = drawingToolBar?
The first seems clunky, I don't even know if it would work. The second seems better but it feels a bit 'wrong'.
Is there another way? Or am I mis-using inheritance here?
You are probably mixing too many functionnalities into your toolbar. If you think MVC, you are missing a Model.
More precisely, the color picker should not be a property of your toolbar. The color picker is a property of your tool. Each drawing tool should be self contained and have its own color picker. If all drawing tools need to share the same color, you'll need a Drawing model that is shared by all drawing tools.
I would also change the relation between the Toolbar and its tools in the other direction. A toolbar has tools, but the tools themselves should be self contained and not have a reference to their containing toolbar.
The Java / Swing model is very clean on how it works with toolbars. You could get some inspiration from it : http://download.oracle.com/javase/tutorial/uiswing/components/toolbar.html
I develop with FlashDevelop3 R2 and the Flex 3.3 SDK and there are many occasions where I must use the embed metadata tag as such:
[Embed(source="path/to/file")]
private var Asset:Class;
I understand the above all well and good, and I am thankful it exists because I do not like to open the flash IDE too often.
When I am going through other authors classes lately, I have found an interesting metadata tag that I do not understand:
[Event(name="", type="")]
I have yet to see a situation where I require this, and furthermore I really just do not understand what it is for.
Thank in advance for your help.
Brian Hodgeblog.hodgedev.com hodgedev.com
These [Event(name, type)] declarations describe which events a class instance is likely to dispatch.
They are actually useful for code completion - for instance when you type: mySprite.addEventListener(, your code editor (Flex Builder or FlashDevelop) will display a meaningful list of events that this object can dispatch.
So you can add these declarations in your code and benefit from a richer code completion.
Also note that this works with custom Event classes (see FlashDevelop's new Event class template).
package mycomp {
import flash.events.Event;
public class MyEvent extends Event {
public const SOME_EVENT:String = "someEvent";
// required Event type declarations
}
}
package mycomp {
[Event(name="someEvent", type="mycomp.MyEvent")]
public class MyComp extends Sprite {
}
}
package myproject {
import mycomp.MyComp;
public class MyProject {
function MyProject() {
var mc:MyComp = new MyComp();
mc.addEventLister( //completes: SOME_EVENT + Sprite events
}
}
}
We use it for binding custom events to our custom MXML components. This tag allows you to reference it from MXML. See documentation:
[Event(name="enableChanged", type="flash.events.Event")]
class ModalText extends TextArea {
...
}
<MyComp:ModalText enableChanged="handleEnableChangeEvent(event);"/>
The compiler will complain, however, if you try to refer to an event on an mxml tag that was not declared with an event metatag.