Как работает привязка свойства `text` TextEdit в QtQuick? - PullRequest
0 голосов
/ 08 мая 2018

Я новичок в QML и пытаюсь руководствоваться поведением стандартных компонентов QtQuick в качестве руководства.

Я хотел реализовать компонент пользовательского ввода так, как работает TextEdit. Но теперь меня действительно смущает, как реализовано свойство text.

Гипотеза 1:

TextEdit text предназначен только для записи и всегда отображает то, чему, если оно существует, присваивается / привязывается его свойство text.

Эксперимент 1

Операция

запустить QML

Window {
    visible: true
    property string foo: "foo"
    TextEdit { text: foo }
}

Введите что-либо в TextEdit

Ожидается Текст всегда отображает "foo" и не может быть отредактирован.

Фактический Текст изменился в зависимости от того, что вы ввели.

Заключение Гипотеза 1 неверна.

Гипотеза 2:

Свойство text устанавливается на то, к чему оно привязывается при инициализации. И как только пользователь отредактирует его, text присваивается новое значение, которое нарушает привязку.

Эксперимент 2

Операция

запустить QML

Window {
    visible: true
    property string foo: "foo"
    TextEdit { id: t1; text: foo; x: 0; }
    TextEdit { id: t2; text: t1.text; x: 100 }
}

введите что-нибудь в t2, а затем введите что-нибудь в t1

Ожидается После редактирования t2 редактирование t1 больше не будет изменять отображение t2.

Фактический t2 может редактироваться исключительно. Но как только t1 снова редактируется, дисплей t2 снова привязывается к t1.

Заключение Гипотеза 2 неверна.

Гипотеза 3:

TextEdit имеет что-то вроде internalText, которое представляет то, что вводит пользователь. И TextEdit отображает либо internalText, либо text, в зависимости от того, что изменилось последним.

Эксперимент 3

Операция

запустить QML

Window {
    visible: true
    property string foo: "foo"
    TextEdit { id: t1; text: foo; x: 0; }
    Button { x: 100; onClick: foo = "bar" } // A custom button
}

типа "блаблабла" в т1

нажать на кнопку

типа "блаблабла" в т1

нажмите кнопку, нажмите кнопку, нажмите кнопку тысячу раз

Ожидается t1 может быть отредактировано, и при нажатии кнопки дисплей сбрасывается до «бара».

Фактический При первом щелчке дисплей устанавливается на «полосу», и после этого нажатие на кнопку вообще не действует.

Заключение Гипотеза 3 неверна ... Что за ... ??

И ...

После прочтения QML Reference несколько раз несколько раз, особенно части Binding Property , я не знаю, как такое свойство, которое может быть как записано, так и прочитано (также не похоже на 2- способ связывания угловых). Я озадачен.

И после выполнения эксперимента 3 я действительно растерялся, может кто-нибудь объяснить, как это работает?

1 Ответ

0 голосов
/ 09 мая 2018

Привязки больше похожи на мета-свойство, чем на фактическое значение. Это легко понять, если представить, как это работает со стороны c ++.

Привязки реализуются с использованием сигналов и слотов. Простая строка QML

text: foo.text

в качестве примера будет эквивалентен следующему коду c ++ (упрощенно):

// first: call the getter of text on foo, and the setter on this
this->setText(foo->text());
// second: connect the change signal of foo to this
connect(foo, SIGNAL(textChanged(QString)),
        this, SLOT(setText(QString)));

Как видите, привязка в основном: «Присвойте мне текущее значение, и всякий раз, когда ваше значение изменяется, обновляйте мое значение до вашего». Но поскольку у «this» все еще есть собственная копия текста, вы можете изменить ее, вызвав this->setText("something"), не нарушая привязку (или, в терминах c ++ - сигнальное соединение)

Это также объясняет 2-й (и 1-й) эксперимент: всякий раз, когда вы изменяете текст t2 в GUI, внутренний текст t2 обновляется. Однако, поскольку привязка все еще существует, каждый раз, когда вы изменяете t1, t1 испускает сигнал textChanged и, таким образом, также обновляет t2.

Теперь для 3-го эксперимента это немного сложно. Код на C ++ сильно упрощен и объясняет только то, что происходит, а не то, как он на самом деле работает. В третьем случае мы должны взглянуть на javascript сторону qml. Более конкретно: Как создаются привязки из JavaScript:

// the qml line
text: foo
// is eqivalent to the js
t1.text = Qt.binding(function(){return foo;})

Таким образом, вы на самом деле не присваиваете значение t1.text, а «объект привязки». (Функция Qt.binding совершает магию и возвращает такой объект). Это внутренне делает то же самое, что и код c ++, приведенный выше, но с одним отличием. Когда вы назначаете новое значение для t1.text, как вы делали это для кнопки, старая привязка удаляется вместе с сигнальным соединением, когда вы заменяете объект привязки новым значением.

Таким образом, в вашем коде JS в кнопке вы заменяете объект привязки значением «bar», тем самым уничтожая его. Редактирование текста из графического интерфейса пользователя не разрушает привязку, так как изменяется только внутреннее значение, и фактически свойство не присваивается свойству из QML.

РЕДАКТИРОВАНИЕ: Теперь причина, по которой последующие нажатия кнопок ничего не делают: после однократного нажатия кнопки foo устанавливается на «bar», что вызывает сигнал textChanged и, таким образом, изменяет t1 , Однако, когда вы в следующий раз нажмете кнопку, и foo снова будет установлен на bar, он ничего не делает, потому что он уже «bar». Вы ничего не меняете, устанавливая на то же значение, что и сейчас. Представьте себе реализацию метода установки следующим образом:

void setText(QString text) {
    if(this->text == text)
        return;
    this->text = text;
    emit textChanged(text);
}

Если вы измените свой код, например, так:

Button { x: 100; onClick: foo = t1.text + "bar" }

Он всегда будет работать и обновлять foo соответственно, так как это выражение всегда генерирует новое значение для foo.

Я надеюсь, что смогу объяснить поведение, понятное вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...