2014-09-05 2 views
0

Работа с незнакомой концепцией (мне) асинхронного и управляемого событиями программирования. Я борюсь с правильной структурой моих программ в AS3.Структура AS3 в отношении модальных диалогов

Что я хочу сделать, это написать класс, который представляет пользователю диалоговое окно с некоторым текстом (отправляется конструктору) и двумя кнопками «Да» и «Нет». К счастью, это уже не проблема для меня. Проблема возникает при выборе правильной структуры программы для получения той кнопки, на которую нажата кнопка.

Предположим, у меня есть Main.as, который в какой-то момент вызывает новый MyDialog, мой теоретический класс диалога. У меня есть getter в MyDialog.as, который устанавливает переменную myButton, которая по умолчанию равна 0, 1 если нажата кнопка «Да» и 2, если «Нет» нажата.

Очевидно, что я не могу создать диалог, а затем сразу же использовать геттер, у пользователя не было бы времени нажать любую кнопку, для этого может потребоваться какое-то время. Как я вижу, у меня должен быть цикл таймера (или фрейм-события) в Main.as, который постоянно использует getter для просмотра myButton, а затем действует соответственно, когда он изменяется.

Это кажется неправильным для меня. У моего Main.as должно быть много флагов штата для каждого создаваемого диалога. Это было бы грязно и, похоже, противоречит принципам программирования, управляемого событиями.

Я понимаю, что MyDialog может просто создать графику, а затем в Main.as вызвать событие, когда нажаты кнопки в этом диалоге, но это похоже на инкапсуляцию Object Orientated Programming, где MyDialog должен быть полностью автономным ,

Итак, есть ли какие-либо из моих возможностей правильный способ сделать это или я что-то пропустил? Любые мысли по этому поводу были бы с благодарностью восприняты. Я не лучший в мире кодер, и этот новомодный материал начинает причинять вред моей старой голове через некоторое время :)

+1

Для чего это событие. отправьте событие, когда нажата любая кнопка, и поймайте их, затем примите меры. – BotMaster

ответ

-1

Просто зарегистрируйте кнопки для функций, которые вы хотите, чтобы их вызывали при нажатии. Вы можете передать их через конструктор, как так ...

package { 
    public class Modal extends Sprite { 
     public function Modal(message:String, yes:Function, no:Function) { 
      // Draw Background 
      graphics.beginFill(0xd9d9d9, 1); 
      graphics.drawRect(0, 0, 500, 300); 
      graphics.endFill(); 

      // Create Text 
      var txt:TextField = new TextField(); 
      txt.text = message; 
      addChild(txt); 

      // Create Yes Button 
      var btnYes = new Button(); 
      addChild(btnYes) 
      btnYes.addEventListener("click", yes); 

      // Create No Button 
      var btnNo = new Button(); 
      addChild(btnNo) 
      btnYes.addEventListener("click", no); 
     } 
    } 
} 

вида, что вам нужно импортировать соответствующие классы, и вы можете использовать совершенно другой класс для кнопок, но суть остается. Фактически, если вы не хотите использовать прослушиватели событий в удаленных функциях, вы можете просто передать произвольные функции с помощью настраиваемых аргументов.

package { 
    private var funcYes:Function; 
    private var argsYes:Array; 

    private var funcNo:Function; 
    private var argsNo:Array; 

    public class Modal extends Sprite { 
     public function Modal(message:String, yes:Function, no:Function, yesArgs:Array = null, noArgs:Array = null) { 
      // Draw Background 
      graphics.beginFill(0xd9d9d9, 1); 
      graphics.drawRect(0, 0, 500, 300); 
      graphics.endFill(); 

      // Create Text 
      var txt:TextField = new TextField(); 
      txt.text = message; 
      addChild(txt); 

      // Create Yes Button 
      var btnYes = new Button(); 
      btnYes.name = "yes"; 
      addChild(btnYes) 
      btnYes.addEventListener("click", buttonListener); 

      // Create No Button 
      var btnNo = new Button(); 
      btnNo.name = "no"; 
      addChild(btnNo) 
      btnYes.addEventListener("click", buttonListener); 

      // Store functions and args for later use. 
      funcYes = yes; 
      argsYes = yesArgs; 
      funcNo = no; 
      argsNo = noArgs; 
     } 

     private function buttonListener(e:MouseEvent):void { 
      switch (e.currentTarget.name) { 
       case "yes": 
        if (argsYes != null) { 
         funcYes.apply(null, args); 
        } else { 
         funcYes(); 
        } 
       case "no": 
        if (argsNo != null) { 
         funcNo.apply(null, args); 
        } else { 
         funcNo(); 
        } 
        break; 
      } 
     } 
    } 
} 
+0

Спасибо, я не рассматривал возможность передачи функций, которые, казалось бы, удовлетворяли бы требованиям как ООП, так и управляемых событиями программирования. Это действительно очень умно. – Jerry

+0

Я беру его в какой-то момент, мне нужно сделать funcYes = да; и funcNo = no; ? И должна ли переменная args быть argsYes и argsNo, как это целесообразно в методах .apply? – Jerry

+0

Я полностью забыл добавить это во втором примере (oops). Правильно, теперь вы можете увидеть соответствующее назначение в конце конструктора. – Atriace

-1

Ответ, который я должен написать, - это путь к обширному ... вот почему я пытаюсь разбить его на несколько шагов.

  1. Подробнее о концепции ООП Узнайте больше о концепциях ООП. ООП в основном разделяет различные проблемы вашего приложения на состояние, поведение и связь между аспектами вашего приложения.
  2. Получите хорошее представление о MVC (S). Шаблон MVC (S) (модель View Controller Service) - стандартный шаблон де-факто для деконструирования вашего приложения на отдельные слои.
  3. Читайте о каркасах, подобных http://www.robotlegs.org/. Это в основном хорошая реализация MVCS и ее применение.

robotlegs должно предоставить вам хорошее представление о том, как должны быть структурированы вещи. Трудная часть в основном заставляет все компоненты познакомиться друг с другом. robotlegs решает эту проблему очень хорошо.

Более технический ответ: у вас есть модель, которая в основном является объектом данных.

package samples.model { 

    public class SimpleValueModel extends EventDispatcher { 

    private var _value:int; 

    public function get value():int { return _value; } 

    public function set value(v:int):void { 
     if (_value == v) return; 
     _value = v; 
     dispatchEvent(new Event('valueChanged')); 
    } 
    } 
} 

Теперь каждый класс заинтересован в данных и, если она меняется, необходима ссылка на него, чтобы прочитать его значение:

private var _model:SimpleValueModel; 

public function get model():SimpleValueModel { return _model; } 

public function set model(value:SimpleValueModel):void { 
    if (_model) _model.removeEventListener('valueChanged', model_valueChangeListener); 
    _model = value; 
    if (_model) { 
    _model.addEventListener('valueChanged', model_valueChangeListener); 
    } 
    setModel(_model); 
} 

protected function setModel(value:SimpleValueModel):void { 
    if (value) { 
    // value is set 
    } else { 
    // value is null. 
    } 
} 

protected function model_valueChangeListener(event:Event):void { 
    setModel(_model); 
} 

Хитрость теперь, чтобы передать ссылки вокруг. Это делается лучше всего благодаря инъекции зависимостей (обычно используется другой шаблон проектирования). D.i. рамки позаботятся об этом (например, роботы).

Надеюсь, я мог бы предложить некоторые указатели.

+0

Благодарим вас за ответ. У меня, конечно, много чтения. Особенно интересно узнать о Robotlegs. Мне бы хотелось, чтобы оба текущих ответа отметили отметку, но сайт не позволяет этого. – Jerry