У меня есть следующий код

qx.Class.define("myproject.EditorArea",
{
  extend : qx.ui.container.Composite,

  events : {
  },

   statics :
   {
   },

  members :
  {
    __htmlArea : null,
    __txtArea : null,

    setWidth : function( value )
    {
      this.__htmlArea.setWidth( value );
      this.__txtArea.setWidth( value );
      return( value );
    },
    setHeight : function( value )
    {
      this.__htmlArea.setHeight( value -19 );
      this.__txtArea.setHeight( value -19 );
      return( value );
    }

},

   /**
    * Constructor
   * @param sHtml {String} the initial html value for this widget.
    */
   construct : function( sHtml )
  {
   this.base(arguments);

    this.setLayout( new qx.ui.layout.VBox(1));

    var container = new qx.ui.container.Composite(new qx.ui.layout.HBox( 1, "right" )).set( {height:18} );
    this.__htmlArea = new qx.ui.embed.Html( sHtml );
    this.add(this.__htmlArea);
    this.__txtArea = new qx.ui.form.TextArea("");
  }
});

При вызове setWidth () из класса EditorArea фреймворк всегда вызывает суперфункцию.

Другими словами

var editor = new myproject.EditorArea( somehtml );
editor.setWidth( 460 );

Вызывает qx.ui.container.Composite.setWidth () вместо myproject.EditorArea.setWidth ().

Переопределенная функция никогда не достигается. Как можно переопределить эти функции установки?

3
Raymond 15 Июн 2016 в 13:07
Позвольте мне выскочить, как Клиппи, и сказать: похоже, вы пытаетесь создать свой собственный виджет. У qooxdoo есть рекомендуемый и хорошо задокументированный способ сделать это, и я думаю, вам будет лучше, если вы последуете ему. Поскольку это не ваш вопрос, я не буду вдаваться в подробности. Вот несколько ссылок. Если вам нужна помощь, спросите здесь. manual.qooxdoo.org/5.0.1/pages/desktop/ui_develop. html news.qooxdoo.org/tutorial-part -4-2-custom-widgets-4 github.com/qooxdoo/qooxdoo/blob/release_5_0_1/framework/source/…
 – 
voger
15 Июн 2016 в 17:46
Также я думаю, что привязка данных будет более подходящей для вашего случая. Опять же, поскольку вопрос не в привязке данных, я не буду вдаваться в подробности, но вот ссылка для начала. Еще раз, если вам нужна помощь, спросите manual.qooxdoo.org/5.0.1/ pages / data_binding /…
 – 
voger
15 Июн 2016 в 17:49

5 ответов

Функции получения и установки генерируются программно во время qx.Class.define (). Как правило, не стоит с ними связываться. Если вы хотите свой собственный, вам лучше создать функции setMyWidth () и setMyHeight (), то есть функции с каким-то не автоматически сгенерированным именем.

Если вы действительно хотите, чтобы имена функций были setWidth / setHeight, вы можете попробовать создать эти функции в разделе defer определения класса. Элемент defer карты, переданный в qx.Class.define, находится на том же уровне, что и конструкция, события, статика, члены (см. Документацию), и код в его функции запускается после того, как класс полностью определен. Вы можете переопределить / полностью перезаписать автоматически сгенерированные методы получения и установки, добавив туда свою пользовательскую функцию. Но вы здесь на неизведанной территории, и я не советую этого делать.

Derrell

4
Derrell Lipman 15 Июн 2016 в 14:31

Как уже сказал Деррелл, переопределение автоматически сгенерированных установщиков и получателей для свойств qooxdoo возможно с помощью уловок, но не рекомендуется.

Но для вас может быть решение, переопределив средство применения свойства _applyDimension для ширины и высоты, которое определено в qx.ui.core.LayoutItem.

Заявитель вызывается при каждом изменении свойства. Прочтите соответствующую документацию по адресу http://demo.qooxdoo.org/current/ apiviewer / # qx.core.Property

Ваше переопределение будет следующим:

_applyDimension : function(newValue, oldValue, propertyName) {
  if(propertyName == "width") {
    this.__htmlArea.setWidth( newValue );
    this.__txtArea.setWidth( newValue );
  }
  if(propertyName == "height") {
    this.__htmlArea.setWidth( newValue-19 );
    this.__txtArea.setWidth( newValue-19 );
  }

  this.base(arguments, newValue, oldValue, propertyName);
}

Важно вызвать метод суперкласса, вызвав здесь this.base(arguments,...), чтобы не нарушать функциональность восходящего потока на пути наследования, или, конечно, вы хотите сделать это явно.

Этот способ безопасен и задокументирован.

3
level420 15 Июн 2016 в 15:46

Причина, по которой ваши setHeight и setWidth не вызываются, заключается в том, что вы никогда не вызываете их в своем примере; взгляните на эту версию своего примера, и вы увидите, что setWidth / setHeight в производных классах вызывается если вы вызываете их (вам нужно будет щелкнуть Кнопка «Журнал», чтобы увидеть результаты отладки, подтверждающие это)

qx.Class.define("myproject.EditorArea", {
  extend: qx.ui.container.Composite,

  members: {
    __htmlArea: null,
    __txtArea: null,

    setWidth: function(value) {
      this.debug("in setWidth");
      this.__htmlArea.setWidth(value);
      this.__txtArea.setWidth(value);
      return (value);
    },
    setHeight: function(value) {
      this.debug("in setHeight");
      this.__htmlArea.setHeight(value - 19);
      this.__txtArea.setHeight(value - 19);
      return (value);
    }

  },

  construct: function(sHtml) {
    this.base(arguments);

    this.setLayout(new qx.ui.layout.VBox(1));
    this.__htmlArea = new qx.ui.embed.Html(sHtml);
    this.add(this.__htmlArea);
    this.__txtArea = new qx.ui.form.TextArea("");
  }
});

var test = new myproject.EditorArea();
test.set({ width: 200, height: 300 }); // outputs "in setWidth" and "in setHeight" 
test.set({ width: 250, height: 350 }); // outputs "in setWidth" and "in setHeight"

(Однако обратите внимание, что пока это работает на игровой площадке, компилятор отладки не позволит вам переопределить аксессоры свойств - я открыл проблему, чтобы обсудить это здесь https://github.com/qooxdoo/qooxdoo/issues/9053)

Более широкая картина того, чего вы пытаетесь достичь, - это встраивать виджеты в другой виджет и управлять макетом, но выбранный вами подход не будет работать, потому что вы не вызываете суперкласс setWidth и setHeight, это означает, что вы предотвратите виджет никогда не иметь ничего, кроме нулевой ширины и высоты. Независимо от того, насколько велика ваша html-область и текстовая область, они никогда не будут видны, потому что их контейнер имеет нулевую ширину / высоту.

Правильный способ изменить способ работы макета - это либо выбрать другой макет (например, qx.ui.layout. * Class), либо потенциально написать свой собственный, хотя ИМХО, это редко требуется, учитывая гибкость существующих классов макета.

:: EDIT :: Хотя я отмечал выше, что компилятор отладки не позволяет переопределять методы доступа к свойствам, это изменилось с 22 июня 2016 года. Qooxdoo был обновлен для поддержки переопределения методов доступа к свойствам, определенных в суперклассы; это находится в основной ветке и будет частью стабильного выпуска Qooxdoo 6.0.

3
johnspackman 22 Июн 2016 в 17:51

Это не способ qooxdoo, потому что:

  1. Для решения задачи обычно используется привязка + слушатель + верстальщик.
  2. В этом случае установщик свойств работает быстро, потому что диспетчер компоновки планирует обновление в своей очереди, но что, если оно выполняется медленно? Свойство спроектировано так, чтобы быть быстрым и легко читаемым разработчиком. Вызов установщика / получателя не должен занимать много времени.
2
Ivan Pogorelov 16 Июн 2016 в 09:32

Кроме того, просто чтобы добавить к обсуждению, когда мы устанавливаем свойство, иногда мы не просто хотим одновременно делать что-то еще, как в случае с этим вопросом. Мы также можем захотеть преобразовать значение перед его установкой, проверить его или просто проверить, находится ли оно в правильном формате. Наряду с _apply qooxdo предоставляет другие ключи в определениях свойств. Например

properties : {
  myProp : {
        apply : "_applyMyProp",
        transform: "_transformMyProp",
        check: "_checkMyProp",  
        validate: "_validateMyProp"}
},

members :
{
  _applyMyProp : function(value, old, name) {
    // do something with the value 
  },

  _transformMyProp: function(value){
    // transform the value before being checked and validated and set
  },

  _checkMyProp: function(value){
    // check the value when on debug mode
  },

  _validateMyProp: function(value){
   // validate the value before set even when not in debug mode
  },
}

Подробнее см. http://manual.qooxdoo.org/5.0.1 /pages/core/defining_properties.html

1
voger 16 Июн 2016 в 08:27