У меня есть следующий код
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 ().
Переопределенная функция никогда не достигается. Как можно переопределить эти функции установки?
5 ответов
Функции получения и установки генерируются программно во время qx.Class.define (). Как правило, не стоит с ними связываться. Если вы хотите свой собственный, вам лучше создать функции setMyWidth () и setMyHeight (), то есть функции с каким-то не автоматически сгенерированным именем.
Если вы действительно хотите, чтобы имена функций были setWidth / setHeight, вы можете попробовать создать эти функции в разделе defer определения класса. Элемент defer карты, переданный в qx.Class.define, находится на том же уровне, что и конструкция, события, статика, члены (см. Документацию), и код в его функции запускается после того, как класс полностью определен. Вы можете переопределить / полностью перезаписать автоматически сгенерированные методы получения и установки, добавив туда свою пользовательскую функцию. Но вы здесь на неизведанной территории, и я не советую этого делать.
Derrell
Как уже сказал Деррелл, переопределение автоматически сгенерированных установщиков и получателей для свойств 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,...)
, чтобы не нарушать функциональность восходящего потока на пути наследования, или, конечно, вы хотите сделать это явно.
Этот способ безопасен и задокументирован.
Причина, по которой ваши 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.
Это не способ qooxdoo, потому что:
- Для решения задачи обычно используется привязка + слушатель + верстальщик.
- В этом случае установщик свойств работает быстро, потому что диспетчер компоновки планирует обновление в своей очереди, но что, если оно выполняется медленно? Свойство спроектировано так, чтобы быть быстрым и легко читаемым разработчиком. Вызов установщика / получателя не должен занимать много времени.
Кроме того, просто чтобы добавить к обсуждению, когда мы устанавливаем свойство, иногда мы не просто хотим одновременно делать что-то еще, как в случае с этим вопросом. Мы также можем захотеть преобразовать значение перед его установкой, проверить его или просто проверить, находится ли оно в правильном формате. Наряду с _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
Похожие вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript/JS) и его различных диалектах/реализациях (кроме ActionScript). Обратите внимание, что JavaScript — это НЕ Java. Включите все теги, относящиеся к вашему вопросу: например, [node.js], [jQuery], [JSON], [ReactJS], [angular], [ember.js], [vue.js], [typescript], [стройный] и т. д.