Миграция кода с Open Laszlo 3.3 на 5.0: TypeError: Ошибка № 1009: невозможно получить доступ к свойству или методу нулевой ссылки на объект

Я столкнулся с проблемой, когда запускаю этот код в 5.0, но он отлично работает в 3.3. Я установил все, но все равно это создает проблему. Я делаю это неправильно?

<canvas width="1000" height="584">

      <drawview width="200" height="300" 
              x="12" 
              y="12">
        <handler name="onwidth">
            this.redraw();
        </handler>
        <handler name="onheight">
            this.redraw();
        </handler>
        <method name="redraw">
            this.clear();
            var roundness = 5;
            this.beginPath();
            this.moveTo(roundness, 0);
            this.lineTo(this.width - roundness, 0);
            this.quadraticCurveTo(this.width, 0, this.width, roundness);
            this.lineTo(this.width, this.height - roundness);
            this.quadraticCurveTo(this.width, this.height, this.width - roundness, this.height);
            this.lineTo(roundness, this.height);
            this.quadraticCurveTo(0, this.height, 0, this.height - roundness);
            this.lineTo(0, roundness);
            this.quadraticCurveTo(0, 0, roundness, 0);
            this.closePath();

            var g = this.createRadialGradient(-this.width * .5, -this.height *.5, .7, 1.5 * this.width, 1.5 * this.height, 0)
            this.globalAlpha = 0;
            g.addColorStop(0, 0x000000);
            this.globalAlpha = 0.8;
            g.addColorStop(1, 0xffffff);

            this.setAttribute("fillStyle", g);
            this.fill();
        </method>
    </drawview>
</canvas>

person karthick    schedule 27.08.2012    source источник


Ответы (1)


Обработчики onwidth и onheight вызываются во время инициализации прорисовки, в момент времени, когда инициализация компонента еще не завершена. Если вы проверяете атрибут isinated компонента, вы можете убедиться, что метод перерисовки вызывается только тогда, когда компонент готов. Я добавил в этот пример отладочный вывод, чтобы показать вам, что происходит:

<drawview id="dv" width="100%" height="100%" 
      x="12" 
      y="12">
  <attribute name="isready" value="false" type="boolean" />
  <handler name="oncontext">
    this.setAttribute("isready", true);
    this.redraw();
  </handler>
  <handler name="onwidth">
    Debug.write('onwidth: calling redraw()');
    this.redraw();
  </handler>
  <handler name="onheight">
    Debug.write('onheight: calling redraw()');
    this.redraw();
  </handler>
  <method name="redraw">
    Debug.info('redraw: this.ininited=' + this.isinited + ' / isready=' + this.isready);
    if (this.isready) {
      this.clear();
      var roundness = 5;
      this.beginPath();
      this.moveTo(roundness, 0);
      this.lineTo(this.width - roundness, 0);
      this.quadraticCurveTo(this.width, 0, this.width, roundness);
      this.lineTo(this.width, this.height - roundness);
      this.quadraticCurveTo(this.width, this.height, this.width - roundness, this.height);
      this.lineTo(roundness, this.height);
      this.quadraticCurveTo(0, this.height, 0, this.height - roundness);
      this.lineTo(0, roundness);
      this.quadraticCurveTo(0, 0, roundness, 0);
      this.closePath();

      var g = this.createRadialGradient(-this.width * .5, -this.height *.5, .7, 1.5 * this.width, 1.5 * this.height, 0);
      this.globalAlpha = 0;
      g.addColorStop(0, 0x000000);
      this.globalAlpha = 0.8;
      g.addColorStop(1, 0xffffff);

      this.setAttribute("fillStyle", g);
      this.fill();
    }
  </method>
</drawview>

Редактировать: обновлена ​​поддержка кода для использования события oncontext вместо значения isinited.

Я проверил документацию drawview, и в drawview есть специальное событие, называемое событием oncontext. Из документов:

Событие oncontext отправляется, когда контекст готов к использованию, что может занять некоторое время в IE DHTML.

Если вы посмотрите на документацию по рисованию в справочнике OpenLaszlo, вы увидите, что в примерах используется обработчик событий oncontext для рисования на холсте.
Я обновил свое решение, чтобы использовать дополнительный атрибут isready, для которого устанавливается значение true после получения события oncontext. Как вы можете видеть в выходных данных отладки ниже, для параметра isinited установлено значение true до того, как для параметра isready установлено значение true:

onwidth: calling redraw() 
INFO: redraw: this.ininited=true / isready=false 
onheight: calling redraw() 
INFO: redraw: this.ininited=true / isready=false 
INFO: redraw: this.ininited=true / isready=true 

Если вы скомпилируете свой код с ошибками для среды выполнения DHTML, вы должны были увидеть следующее предупреждение:

ВНИМАНИЕ: this.context еще не определен. Пожалуйста, проверьте наличие свойства контекста перед использованием методов рисования и/или зарегистрируйтесь для события oncontext, чтобы узнать, когда свойство будет доступно.

К сожалению, такое предупреждение не отображается для среды выполнения SWF.

person raju-bitter    schedule 27.08.2012
comment
когда я меняю строку на ‹drawview id=dv width=${parent.width} height=${parent.height} x=12 y=12› выдает ту же ошибку. Почему? Естественно, он должен принимать ширину родителя, верно? Это происходит, когда я даю ширину и высоту в процентах - person karthick; 28.08.2012
comment
Я обновил предыдущий ответ. Drawviews уникальны тем, что имеют событие oncontext, которое следует использовать вместо isinitied. Подробности смотрите в ответе. - person raju-bitter; 28.08.2012