How to access QmlStyling Nesting QtObjects? - qt

I want to access nested QtObject in another Qml file. QmlStyling Nesting QtObjects
subDir/Style.qml file
pragma Singleton
import QtQuick 2.0
QtObject {
property int textSize: 40
property color textColor: "green"
property color rectColor: "red"
property QtObject window: QtObject {
property color background: "white";
}
property QtObject border: QtObject {
property QtObject width: QtObject {
property int normal: 1;
property int big: 3;
}
property QtObject color: QtObject {
property color normal: "gray";
property color focus: "blue";
property color disabled: "red";
}
}
}
I want to access it in Screen1.qml
import QtQuick 2.0
import QtQuick.Controls 1.4
import "subDir" 1.0
Item
{
id: rootItem
width: 800; height: 600
Rectangle {
id:myRect
x: 47; y: 61
width: 706; height: 478
color: Style.rectColor // This works correctly
//But this below line doesn't
border.width: Style.border.width.big // I want to access something like this
}
}
In subDir/qmldir file:
singleton Style 1.0 Style.qml
qmldir and Style.qml files are in same folder (Just for info)
qml.qrc File:
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>MainForm.ui.qml</file>
<file>Screen1.qml</file>
<file>subDir/qmldir</file>
<file>subDir/Style.qml</file>
</qresource>

Related

why property binding in dynamic component creation not working?

signal 'clearPinFromDevManager(const QString& pinn)' will be emited repeatedly from cpp file. the signal caught onClearPinFromDevManager:{},so everything in cpp and main.qml files are ok, but 'recvClearPin' does not bind to PasswordWindow.qml component which is created dynamicly.
Note:If code has a problem, what is your solution to fix the problem?thanks
Main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import Terminal 1.0
import QtQuick.Controls 2.12
ApplicationWindow {
id: rootId
visible: true
objectName: "window"
width: Screen.width
height: Screen.height
flags: Qt.FramelessWindowHint
property var component
property var object
property string recvClearPin:""
Rectangle {
id:rootRectId
width: rootId.width
height: rootId.height - headerId.height
color: "#000033"
}
Terminal {
id: terminalId
onSignalToInitTerminal:{
console.log("show Password window.")
component= Qt.createComponent("Ui/PasswordWindow.qml");
object=component.createObject(rootRectId,{clearPin: recvClearPin});
}
//signal will emit repeatedly
onClearPinFromDevManager:{
console.log("signal emited here and pinn is:",pinn)
recvClearPin=pinn
}
}
}
PasswordWindow.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import "../Definitions.js" as Definitions
Item {
id:passwordWindowId
width: parent.width
property string password: ""
property alias clearPin: textEditId.text
Text {
id: passwordWindowTextId
font.family: Definitions.LABEL_FONT_FAMILY; font.pointSize: Definitions.LABEL_POINT_SIZE
text: qsTr("لطفا رمز خود را وارد نمایید")
color: Definitions.LABEL_COLOR
y: Definitions.PAGE_TITLE_Y_POS
x: Definitions.PAGE_TITLE_X_POS
}
Rectangle {
id: textEditRectId
x: passwordWindowTextId.x +10
y: passwordWindowTextId.y + height
width: Definitions.TEXT_EDIT_WIDTH
height: Definitions.TEXT_EDIT_HEIGHT
border.width: 1
border.color: "#000000"
radius: 10
color: Definitions.GENERAL_COLOR
TextEdit {
id: textEditId
width: parent.width
height: parent.height
text: ""
font.family: Definitions.GENERAL_FONT_FAMILY; font.pointSize: Definitions.GENERAL_POINT_SIZE
color: "blue"
focus: true
verticalAlignment: TextEdit.AlignVCenter
horizontalAlignment: TextEdit.AlignHCenter
onTextChanged: {
console.log("texttttttttttttttttt:",text);
}
}
}
}
You do not bind the clearPin in this line: object=component.createObject(rootRectId,{clearPin: recvClearPin});. Instead you create a Json object with a item named 'clearPin' that has the current value of 'recvClearPin'. If you want a binding, use Qt.binding:
object=component.createObject(rootRectId,{clearPin: Qt.binding(function() { return recvClearPing} )});
please provide more information where signal clearPinFromDevManager(const QString& pinn) is connected.
For dynamic objects you should use connect syntax in QML with cpp-objects.
You need register your class wich contains clearPinFromDevManager(const QString& pinn) in QML, then connect it to dynamically created object, or in onComleted-handler, like this:
Declare yous class in CPP/H:
class CrearPinObject : public QObject {
Q_OBJECT
signals:
void clearPinFromDevManager(const QString& pinn);
}
Register it QML engine, main.cpp (or similar):
...
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("CrearPinObjectView", new CrearPinObject);
...
Connect signal using QML-connect syntax (PasswordWindow.qml):
Item {
Component.onCompleted: {
// CrearPinObjectView-object forward automatically
CrearPinObjectView.clearPinFromDevManager.connect(clearPinFromDevManager);
}
function clearPinFromDevManager(pinn) {
console.log(pinn);
}
}
Hope helped!

How to draw an element over following items in QML layouts

I'm working on a DatePicker control for QtQuick.Controls 2.0 I have problem on drawing popup calendar over other page items. does anyone help me on this ?
Component Screenshot
My DatePicker source code:
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Controls 1.4 as OldControls
Rectangle {
id: root
width: childrenRect.width
height: childrenRect.height
clip: true
property bool expanded: false
property bool enabled: true
property alias selectedDate: cal.selectedDate
MouseArea {
height: expanded ? txt.height + cal.height : txt.height
width: expanded ? Math.max(txt.width, cal.width) : txt.width
hoverEnabled: true
enabled: root.enabled
onHoveredChanged: {
expanded = root.enabled && containsMouse
}
TextField {
id: txt
enabled: root.enabled
text: cal.selectedDate
inputMask: "0000-00-00"
}
OldControls.Calendar {
id: cal
anchors.top: txt.bottom
anchors.left: txt.left
visible: expanded
}
}
}
and here is my DatePicker usage in page:
import QtQuick 2.0
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.2
import "./Components"
Item {
anchors.fill: parent
GridLayout {
columns: 2
Text { text: qsTr("Date Filter: ") }
DatePicker {}
Text { text: qsTr("name filter: ") }
TextField {}
}
}

How to set an item property of one qml from main.qml

I waste my time to find how set the visible property to false, the delegate being in an another qml file.
For instance here is a simple example based on Places Map.
Marker.qml
import QtQuick 2.0
import QtLocation 5.6
MapQuickItem {
id: idPointsMarker
sourceItem: Loader{sourceComponent: idRect}
visible: true //if set manually to false, everything works correctly
Component{
id: idRect
Rectangle{
width: 20
height: 20
color: "blue"
}
}
}
and the main.qml
import QtQuick 2.0
import QtQuick.Window 2.0
import QtLocation 5.6
import QtPositioning 5.6
Window {
width: 512
height: 512
visible: true
PositionSource {
...
}
property variant locationOslo: QtPositioning.coordinate( 59.93, 10.76)
PlaceSearchModel {
...
}
Map {
id: map
anchors.fill: parent
plugin: Plugin {name: "osm"}
center: locationOslo
zoomLevel: 13
MouseArea {
id : mouseMap
anchors.fill: parent
onDoubleClicked: {
console.log("DoubleClicked")
Marker.idPointsMarker.visible = false // pb is here
}
}
MapItemView {
model: searchModel
delegate: Marker{
coordinate: place.location.coordinate
}
}
}
}
I wish to toggle the visibility to false on doubleclick. I am not able to access the property anyhow the way i write it. What is the correct syntax?
Sorry for a so simple question. Thanks for help.
You do not have to set the property in main.qml, you must do it in Marker.qml, since the elements of Marker.qml can access all the elements of main.qml. One solution is to establish a property of type bool that manages the visibility and that changes in the double click:
main.qml
Map {
[...]
property bool isVisibleItems: true
MouseArea {
id : mouseMap
anchors.fill: parent
onDoubleClicked: map.isVisibleItems = !map.isVisibleItems
}
[...]
Marker.qml
import QtQuick 2.0
import QtLocation 5.6
MapQuickItem {
id: idPointsMarker
sourceItem: Loader{sourceComponent: idRect}
visible: map.isVisibleItems
Component{
id: idRect
Rectangle{
width: 20
height: 20
color: "blue"
}
}
}
In the following link there is an example

How to make a QML toggle button that tracks/controls any boolean property

My QML/QtQuick exercise for today is to make a little ToggleButton widget that I can instantiate to monitor the state of a specified boolean QML property, and that also toggles that property's state when I click on the ToggleButton.
So far I have this for my ToggleButton component:
// 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";
}
}
}
.... and here is my little test harness that I use to see whether it works the way I want it to, or not:
// 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
}
}
You can run this by saving the code to ToggleButton.qml and main.qml (respectively) and then running "qmlscene main.qml".
Note that if you click on the blue or green rectangles, it works as expected; the boolean "lighten" property of the Rectangle object is toggled on and off, causing the Rectangle to change color, and the associated ToggleButton also reacts appropriately (by turning itself red when the "lighten" property is true, and gray when the "lighten" property is false).
So far, so good, but if you then click on the ToggleButton itself, the binding is broken: that is, clicking on the ToggleButton causes the ToggleButton to turn red/gray as expected, but the rectangle's color doesn't follow suit, and after doing that, clicking on the rectangle no longer causes the ToggleButton's state to change, either.
My question is, what is the trick to doing this properly, so that I always have a bidirectional correspondence between the ToggleButton and the property it is tracking? (Note that the ideal solution would add as little code as possible to main.qml, since I'd like this functionality to be encapsulated inside ToggleButton.qml, to minimize the amount of complexity exposed to the rest of my QML app)
The reason this does not work is that you are overwriting the binding with a fixed value. By manually assigning a value in you onClicked you overwrite the binding with a value.
The problem is: QML does not support 2way bindings right now. There are, however, some tricks to create one. See http://imaginativethinking.ca/bi-directional-data-binding-qt-quick/
Note: Instead of using the isActive property like this, why not use the checked state of the button? (From the documentation) This way the binding won't break, even if you click the button:
// 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";
}
}
}
It looks like one way to solve this problem is to have the ToggleButton declare its state using an alias-property, rather than a regular property. That way there is only the one external property (since the ToggleButton's internal property is really just an alias to the external one), and therefore no bidirectional binding is necessary. Here's an updated version of the QML code that works as expected:
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
}
}

Qt 5: read property inside Loader

How to read property timeout located inside Loader object in Qt5 QML Quick 2.0?
import QtQuick 2.0
Rectangle {
width: 100
height: 100
color: "black"
property Component comp1 : Component {
Rectangle {
id: abc
property int timeout: 5000
width: 10; height: 10;
color: "red"
}
}
Loader {
id: loader
sourceComponent: comp1
}
Component.onCompleted: console.log( "timeout: " + loader.item.abc.timeout )
}
TypeError: Cannot read property 'timeout' of undefined
You have a few issues in your code, namely:
1) You do not assign an id identifier to your component object.
2) You are trying to inherit Component with a property which is needless in this simple code.
3) You do not use the item property properly for the Loader element.
4) You are referring to a property name rather the id of the Component. This is again back to the needless inheritance.
Based on the official documentation, you should be doing something like this:
import QtQuick 2.0
Rectangle {
width: 100
height: 100
color: "black"
Component {
id: comp1
Rectangle {
id: abc
property int timeout: 5000
width: 10; height: 10;
color: "red"
}
}
Loader {
id: loader
sourceComponent: comp1
}
Component.onCompleted: console.log( "timeout: " + loader.item.timeout )
}

Resources