why property binding in dynamic component creation not working? - qt

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!

Related

Pass value from child QtQuck QML to main QML

I have to pass some values from child QML open with component to main QML and use them to do something in main QML.
This is my two QML files:
I have mail.qml like this:
import QtQuick 2.10
import QtQuick.Window 2.10
import QtQuick.Controls 2.3
ApplicationWindow {
id: applicationWindow
property string selected_contact_account_str: String()
/* Contacts */
function createContacts() {
var component = Qt.createComponent("ContactList.qml");
console.log("Component Status:", component.status, component.errorString());
var window = component.createObject(applicationWindow, {"x": 0, "y": 0});
window.showFullScreen();
}
Icon {
id: contacts
anchors.top: parent.top
anchors.topMargin: 60
anchors.left: parent.left
anchors.leftMargin: 20
iconsize: 96
iconsource: "content/contacts_icon.png"
iconname: "Contacts"
fontsize: 14
MouseArea {
anchors.fill: parent
onClicked: createContacts()
}
}
/* End Contacts */
}
And an ContactList.qml with Button:
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Window 2.2
ApplicationWindow {
id: contactsList
Item {
Item {
id: appContainer
anchors.fill: parent
anchors.centerIn: parent
Button {
id: contact_select
text: qsTr("Select")
onClicked: {
// I want to pass value from here to main.qml
// store in selected_contact_account_str
// So I can use it in mail.qml
}
}
}
}
How can I do?
you can use signal and slot to do it.
In
ApplicationWindow
id: contactsList
signal sendmessage(var message)
.
.
.
onClicked: {
contactsList.sendmessage("test");
}
then in first file
function createContacts() {
window.sendmessage.connect(handleMessage)
}
function handleMessage(message){
}

How to set objectName for PopupItem from QML?

QML Popup and derived controls are creating a PopupItem object which is a visual representation of it, but Popup itself is parented to the contentData of the application window. objectName specified for Popup is not applied to PopupItem. For example, the following application:
import QtQuick 2.12
import QtQuick.Controls 2.12
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Popup Test")
Button {
text: "Open"
onClicked: dummyPopup.open()
}
Popup {
id: dummyPopup
objectName: "dummyPopup"
x: 100
y: 100
width: 200
height: 300
modal: true
focus: true
}
}
creates PopupItem with empty objectName
Is there a way to set objectName for PopupItem from QML?
Set the objectName of its contentItem upon completion:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Popup Test")
Button {
text: "Open"
onClicked: dummyPopup.open()
}
Popup {
id: dummyPopup
objectName: "dummyPopup"
x: 100
y: 100
width: 200
height: 300
modal: true
focus: true
Component.onCompleted: {
contentItem.objectName = "foo"
print(contentItem)
}
}
}
By the way, if this is for auto tests, I have a hack in C++ that avoids the need to give an objectName to the contentItem:
QObject *TestHelper::findPopupFromTypeName(const QString &typeName) const
{
QObject *popup = nullptr;
foreach (QQuickItem *child, overlay->childItems()) {
if (QString::fromLatin1(child->metaObject()->className()) == "QQuickPopupItem") {
if (QString::fromLatin1(child->parent()->metaObject()->className()).contains(typeName)) {
popup = child->parent();
break;
}
}
}
return popup;
}
You can then use that function like this in your test:
const QObject *newProjectPopup = findPopupFromTypeName("NewProjectPopup");
QVERIFY(newProjectPopup);
QTRY_VERIFY(newProjectPopup->property("opened").toBool());

how to load child1.qml page on to main.qml page calling from another_child.qml page

In my MyHeader.qml cannot load the MyChild2.qml. How to load child qml page on to mmain.qml page calling from another child qml page as shown below.
TestProject Folder
qml Folder
Main.qml
MyChild1.qml
mainui Folder
MyHeader.qml
MyChild2.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
import "."
// Main.qml
ApplicationWindow {
id: rootApp
Loader {
id: loaderPage
anchors.fill: parent
}
MyChild1 {
}
}
// MyChild1.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
import "."
Page {
id: myItem1
anchors.fill: parent
MyHeader {
anchors.top: parent.top
}
}
// MyChild2.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
import "."
Page {
id: myItem2
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#000000"
}
}
// MyHeader.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
import "."
Rectangle {
id: myHeader
width: parent.width
height: dp(30)
color: "lightblue"
Text {
id: loadQML
text: "Load QML"
color: "#000000"
font.pixelSize: dp(20)
MouseArea {
anchors.fill: parent
onClicked: {
myItem1.visible = false
loaderPage.source = "MyChild2.qml"
loaderPage.Top
}
}
}
}
Using the Loader and Connection I am getting Cannot assign to non-existent property "onPageChanged"
import QtQuick 2.10
import "mainui"
ApplicationWindow {
id: rootApp
signal pageChanged(int page);
Loader {
id:rootLoader
anchors.fill: parent
source: "mainui/Page1.qml"
Connections {
target: rootLoader.item
onPageChanged: {
switch(page)
{
case 1: rootLoader.source = "mainui/Page1.qml"; break;
case 2: rootLoader.source = "mainui/Page2.qml"; break;
}
}
}
}
} // APP
Due to scope limitation of Loader you cannot access items outside it. But you can notify the Loader to do some action. In the example below there are 2 components define a signal. The Loader connects this signal to a handler:
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
id: win
width: 400
height: 400
title: "Test"
visible: true
Component {
id: page1
Rectangle {
signal pageChanged(int page);
anchors.fill: parent
color: "orange"
Text {
anchors.centerIn: parent
text: "PAGE 1\nClick to change"
horizontalAlignment: Text.AlignHCenter
}
MouseArea {
anchors.fill: parent
onClicked: {
pageChanged(2);
}
}
}
}
Component {
id: page2
Rectangle {
signal pageChanged(int page);
anchors.fill: parent
color: "lightblue"
Text {
anchors.centerIn: parent
text: "PAGE 2\nClick to change"
horizontalAlignment: Text.AlignHCenter
}
MouseArea {
anchors.fill: parent
onClicked: {
pageChanged(1);
}
}
}
}
Loader {
id: loader
anchors.fill: parent
sourceComponent: page1
Connections {
target: loader.item
onPageChanged: {
switch(page)
{
case 1: loader.sourceComponent = page1; break;
case 2: loader.sourceComponent = page2; break;
}
}
}
}
}

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 use mouseclick area from loaded Form in qml?

below is my code snippet where i'm loading qml ui using dynamic object creation method now i have to implement mousearea which reside in loaded file, can anyone help me to do this
Qt.createQmlObject(" import QtQuick 2.0
Loader {
id: pageLoader
source: '/HomeScreenForm.ui.qml'
anchors.fill: parent
anchors.rightMargin: 0
anchors.leftMargin: 0
anchors.bottomMargin: parent
anchors.topMargin: parent
}
", rectangle7)
Create custom item contains MouseArea. To make the area accessible from outside you can use alias, for example:
MyItem.qml
import QtQuick 2.7
Rectangle {
id: root
color: "yellow"
property alias area: mouseArea
MouseArea {
id: mouseArea
anchors.fill: parent
}
Text {
anchors.centerIn: parent
text: "Click me!"
}
}
And then you can create it dynamically:
import QtQuick 2.7
import QtQuick.Window 2.0
Window {
id: mainWindow
width: 600
height: 600
visible: true
Component.onCompleted: {
var component = Qt.createComponent("MyItem.qml");
if (component.status === Component.Ready) {
var obj = component.createObject(mainWindow);
obj.width = 200;
obj.height = 200;
obj.anchors.centerIn = mainWindow.contentItem;
obj.area.onPressed.connect(
function(mouse){
console.log("pressed at (", mouse.x,",",mouse.y,")")
});
}
}
}
Another way is using Connections, as #derM already noticed.

Resources