2016-07-08 1 views
1

В настоящее время мое упражнение QML/QtQuick состоит в том, чтобы создать небольшой виджет ToggleButton, который я могу создать для проверки состояния указанного логического свойства QML, а также переключает это состояние свойства, когда я нажимаю ToggleButton.Как сделать кнопку переключения QML, которая отслеживает или управляет любым логическим свойством

До сих пор я это для моего ToggleButton компонента:

// Contents of ToggleButton.qml 
import QtQuick 2.2 
import QtQuick.Controls 1.2 
import QtQuick.Controls.Styles 1.4 

Button { 
    property bool isActive: false 

    onClicked: { 
     isActive = !isActive; 
    } 

    style: ButtonStyle { 
     background: Rectangle { 
      border.width: control.activeFocus ? 2 : 1 
      border.color: "black" 
      radius: 4 
      color: isActive ? "red" : "gray"; 
     } 
    } 
} 

.... а вот мой маленький Жгут тест, который я использую, чтобы увидеть, работает ли он так, как я хочу, чтобы он, или нет:

// Contents of main.qml 
import QtQuick 2.6 
import QtQuick.Window 2.2 

Window { 
    visible: true 
    width: 360 
    height: 360 

    Rectangle { 
     property bool lighten: false; 

     id:blueRect 
     x: 32; y:32; width:64; height:64 
     color: lighten ? "lightBlue" : "blue"; 

     MouseArea { 
     anchors.fill: parent 
     onClicked: parent.lighten = !parent.lighten; 
     } 
    } 

    Rectangle { 
     property bool lighten: false; 

     id:greenRect 
     x:192; y:32; width:64; height:64 
     color: lighten ? "lightGreen" : "green"; 

     MouseArea { 
     anchors.fill: parent 
     onClicked: parent.lighten = !parent.lighten; 
     } 
    } 

    ToggleButton { 
     x:32; y:128 
     text: "Bright Blue Rect" 
     isActive: blueRect.lighten 
    } 

    ToggleButton { 
     x:192; y:128 
     text: "Bright Green Rect" 
     isActive: greenRect.lighten 
    } 
} 

Вы можете запустить путем сохранения кода в ToggleButton.qml и main.qml (соответственно), а затем запустить «qmlscene main.qml».

Обратите внимание, что если вы нажмете на синие или зеленые прямоугольники, он будет работать, как ожидалось; логическое свойство «lighten» объекта Rectangle переключается и выключается, в результате чего Rectangle меняет цвет, и соответствующий ToggleButton также реагирует соответствующим образом (поворачивая себя красным, когда свойство «lighten» истинно, а серый, когда «светится» "свойство является ложным).

До сих пор так хорошо, но если вы затем нажмете на ToggleButton, привязка будет нарушена: то есть нажатие на ToggleButton вызывает ToggleButton, чтобы он стал красным/серым, как ожидалось, но цвет прямоугольника не следуя этому примеру, и после этого щелчок по прямоугольнику больше не приводит к изменению состояния ToggleButton.

Мой вопрос в том, что это за трюк для этого, так что у меня всегда есть двунаправленное соответствие между ToggleButton и свойством, которое оно отслеживает? (Обратите внимание, что идеальное решение добавило бы как можно меньше кода в main.qml, так как я хотел бы, чтобы эта функциональность была инкапсулирована внутри ToggleButton.qml, чтобы свести к минимуму сложность, подверженную воздействию остальной части моего приложения QML)

ответ

1

Похоже, один из способов решения этой проблемы является, чтобы иметь ToggleButton объявить свое состояние, используя псевдоним-свойство , а не регулярное свойство. Таким образом, существует только одно внешнее свойство (поскольку внутреннее свойство ToggleButton действительно является просто псевдонимом внешнего), и поэтому не требуется двунаправленная привязка. Вот обновленная версия кода QML, который работает, как ожидалось:

ToggleButton.qml:

// Contents of ToggleButton.qml 
import QtQuick 2.2 
import QtQuick.Controls 1.2 
import QtQuick.Controls.Styles 1.4 

Button { 
    onClicked: { 
     isActive = !isActive; 
    } 

    style: ButtonStyle { 
     background: Rectangle { 
      border.width: control.activeFocus ? 2 : 1 
      border.color: "black" 
      radius: 4 
      color: isActive ? "red" : "gray"; 
     } 
    }  
} 

main.qml:

// Contents of main.qml 
import QtQuick 2.6 
import QtQuick.Window 2.2 

Window { 
    visible: true 
    width: 360 
    height: 360 

    Rectangle { 
     property bool lighten: false; 

     id:blueRect 
     x: 32; y:32; width:64; height:64 
     color: lighten ? "lightBlue" : "blue"; 

     MouseArea { 
     anchors.fill: parent 
     onClicked: parent.lighten = !parent.lighten; 
     } 
    } 

    Rectangle { 
     property bool lighten: false; 

     id:greenRect 
     x:192; y:32; width:64; height:64 
     color: lighten ? "lightGreen" : "green"; 

     MouseArea { 
     anchors.fill: parent 
     onClicked: parent.lighten = !parent.lighten; 
     } 
    } 

    ToggleButton { 
     x:32; y:128 
     text: "Bright Blue Rect" 
     property alias isActive: blueRect.lighten 
    } 

    ToggleButton { 
     x:192; y:128 
     text: "Bright Green Rect" 
     property alias isActive: greenRect.lighten 
    } 
} 
+0

Интересное использование псевдонима недвижимости! Я не видел этого раньше, как это. До сих пор я видел, как они использовали для раскрытия внутренних свойств компонента на поверхности API.Однако есть проблема с дизайном: ваш ToggleButton теперь полагается на что-то из области, из которой он используется. Если вы забыли псевдоним свойства в использовании компонента, QML попытается найти его в любой родительской области. Это может привести к довольно удивительным ошибкам. Также нет никакого намека на то, что пользователь вашего компонента должен добавить это свойство isActive alias, а не просто установить значение, как он будет ожидать. –

5

Причина, по которой это не работает, заключается в том, что вы переписываете привязку с фиксированным значением. При назначении вручную onClicked вы переписываете привязку со значением.

Проблема в следующем: QML не поддерживает привязки 2way прямо сейчас. Есть, однако, некоторые трюки для его создания. См. http://imaginativethinking.ca/bi-directional-data-binding-qt-quick/

Примечание: вместо использования свойства isActive, почему бы не использовать проверенное состояние кнопки? (Из documentation) Таким образом, связывание не сломается, даже если нажать на кнопку:

// Contents of ToggleButton.qml 
import QtQuick 2.2 
import QtQuick.Controls 1.2 
import QtQuick.Controls.Styles 1.4 

Button { 
    //use the "checked" property instead of your own "isActive" 

    checkable: true 

    style: ButtonStyle { 
     background: Rectangle { 
      border.width: control.activeFocus ? 2 : 1 
      border.color: "black" 
      radius: 4 
      color: checked? "red" : "gray"; 
     } 
    } 
}