Russian Qt Forum
Ноябрь 22, 2024, 17:42 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Qt Script. Сделать что-то вроде индексируемой переменной.  (Прочитано 4246 раз)
Susenin
Новичок

Offline Offline

Сообщений: 35


Просмотр профиля
« : Октябрь 08, 2013, 23:45 »

Всем привет.

Хочу, чтобы из скрипта были доступны свойства моего объекта вот так:
Код
Javascript
module.frequency(1) = 15;
var a = module.frequency(2);
 

В строке module.frequency(1) = 15; должно быть не присвоение 15 переменной, ссылку на которую вернет module.frequency(1),
а фактически вызов функции frequency c 2-мя параметрами: 1 - индекс, 2 - значение.
(В функции frequency я пишу число 15 по Modbus в регистр с индексом 1).

Почти то, что нужно описывается в документации http://qt-project.org/doc/qt-5.0/qtscript/qtscript-index.html#property-getters-and-setters

Цитировать
Property Getters and Setters
A script object property can be defined in terms of a getter/setter function, similar to how a Qt C++ property has read and write functions associated with it. This makes it possible for a script to use expressions like object.x instead of object.getX(); the getter/setter function for x will implicitly be invoked whenever the property is accessed. To scripts, the property looks and behaves just like a regular object property.
A single Qt Script function can act as both getter and setter for a property. When it is called as a getter, the argument count is 0. When it is called as a setter, the argument count is 1; the argument is the new value of the property. In the following example, we define a native combined getter/setter that transforms the value slightly:
QScriptValue getSet(QScriptContext *ctx, QScriptEngine *eng)
{
    QScriptValue obj = ctx->thisObject();
    QScriptValue data = obj.data();
    if (!data.isValid()) {
        data = eng->newObject();
        obj.setData(data);
    }
    QScriptValue result;
    if (ctx->argumentCount() == 1) {
        QString str = ctx->argument(0).toString();
        str.replace("Roberta", "Ken");
        result = str;
        data.setProperty("x", result);
    } else {
        result = data.property("x");
    }
    return result;
}

Недостаток 1: эти функции не могут быть методами класса. Соответственно this недоступен.
Недостаток 2: эти функции нужно прокидывать в глобальный объект явно, а хочется, чтобы они были доступны через объект
Код
C++ (Qt)
QScriptEngine eng;
QScriptValue obj = eng.newObject();
obj.setProperty("x", eng.newFunction(getSet), QScriptValue::PropertyGetter|QScriptValue::PropertySetter);
 

Подскажите, что делать? Можно, конечно, попить валерьянки, успокоиться Смеющийся и оставить по 2-му варианту, но вдруг можно сделать красиво?

Что делал.
Вариант 1.
Есть объект со свойствами (так по-русски properties?):
Код
C++ (Qt)
class Module : public QObject
{
   Q_OBJECT
   Q_PROPERTY(quint32 frequency1     READ frequency1     WRITE setFrequency1)
   Q_PROPERTY(quint32 frequency2     READ frequency2     WRITE setFrequency2)
   ...
   Q_PROPERTY(quint32 frequency99   READ frequency99    WRITE setFrequency99)
 
private:
   ...
}
 

Код
Javascript
module.frequency1 = 15;
var a = module.frequency2;
 

Недостатки: некрасиво, много писанины, много возможностей ошибиться.

Вариант 2.
Вместо свойств делаю вызываемые методы:
Код
C++ (Qt)
class Module : public QObject
{
   Q_OBJECT
 
public:    
   Q_INVOKABLE quint32 frequency(quint8 index);
   Q_INVOKABLE void setFrequency(quint8 index, quint32 value);
}
 

Код
Javascript
module.setFrequency(1, 15);
var a = module.frequency(2);
 

Пока у меня реализован 2-й вариант.
Записан
lesav
Частый гость
***
Offline Offline

Сообщений: 235


qnx.org.ru


Просмотр профиля WWW
« Ответ #1 : Октябрь 09, 2013, 15:30 »

Сделать как в первом варианте со свойствами, и обращаться к ним используя магию JS (как к именованному массиву)
Код
Javascript
for(var i=1; i < 255; i++)
{
  module['frequency' + i] = 15
  var a = module['frequency' + i];
}
 
Записан

lesav
Частый гость
***
Offline Offline

Сообщений: 235


qnx.org.ru


Просмотр профиля WWW
« Ответ #2 : Октябрь 09, 2013, 15:33 »

В принципе этот подход можно попробовать и во втором варианте
Записан

Susenin
Новичок

Offline Offline

Сообщений: 35


Просмотр профиля
« Ответ #3 : Октябрь 23, 2013, 11:32 »

Сделать как в первом варианте со свойствами, и обращаться к ним используя магию JS (как к именованному массиву)
Код
Javascript
for(var i=1; i < 255; i++)
{
  module['frequency' + i] = 15
  var a = module['frequency' + i];
}
 
Спасибо, магия JS помогла, так и сделал.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.251 секунд. Запросов: 22.