0

I recently start to learn Qt and QML for prototyping some UI and experienced some issue.

Basically, I have a Rectangle (id: myItem) in TestB.qml which is considered as a button. I also have another Rectangle (id:changedrect) in TestA.qml.

The functionalities I want to implement is when myItem is clicked, the width and height of changedrect in TestA.qml will change.

Here are the hierarchy of directories

enter image description here

My TestA.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import Qt5Compat.GraphicalEffects
import QtQuick.Shapes 2.15
import QtQml 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 2.15
import QtMultimedia
//import "../TestB" as TestB
import "resizeRect.js" as ResizeRectScript
Item {
id: testA

property alias changeRect: changedrect

/** expose the boolean*/
property bool ifSlected: false

Rectangle{

    anchors.fill: parent
        id: changedrect
        x: 10
        y: 10
        width:200
        height: 200
        color:"red"
    
     Component.onCompleted:{
     
    ResizeRectScript.resize(testA.ifSlected,changedrect); // pass boolean flag && id of rect
    
   }
   
      }




//    Loader {
//       id: myLoader
//       source: "../TestB/TestB.qml"
//    }

//    Connections {
//        target: myLoader.item
//        function onMessage(msg) { console.log(msg) }
//    }
}

resizeRect.js

function resize(selectFlag, rectId){
        if(selectFlag = true){
            rectId.width = 100;
            console.log("yes, resize is excuted");
        }
    }

TestB.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import Qt5Compat.GraphicalEffects
import QtQuick.Shapes 2.15
import QtQml 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 2.15
import QtMultimedia
import "../TestA" as TestA

Item{

    TestA.TestA{
        id: testA
    }



    Rectangle {
       id: myItem
       signal message()

       width: 100; height: 100
       color: "pink"

       MouseArea {
           anchors.fill: parent
           onClicked: {
               testA.ifSlected = true;


           }

       }
    }

}

And I instantiated(created object) TestA and TestB on test2.qml

test2.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import Qt5Compat.GraphicalEffects
import QtQuick.Shapes 2.15
import QtQml 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 2.15
import QtMultimedia

import "TestA" as TestA
import "TestB" as TestB
Window {
    width: Screen.width
    height:Screen.height
    flags: Qt.FramelessWindowHint | Qt.BypassWindowManagerHint |Qt.WindowStaysOnBottomHint |
           Qt.NoDropShadowWindowHint /** hide the native menu bar so that the windows takes over whole screen */
    visibility: "FullScreen"
    visible: true
    color: "black"


  TestA.TestA{
  id:test_A
  }
  TestB.TestB{
  id: test_B
  }


}

The problem is

  1. the console message is printed, which means the resize() function from js file is excuted(see below), however the size of rectangle in TestA.qml is not updated. I tried to use Signal from Qt documentation, but the examples did not work either.

Here is the terminal output:

enter image description here

Can someone helps me with this? Thank you so much!!

  • Side note: `if(selectFlag = true)` is incorrect, it should be `if(selectFlag == true)` – Aamir Sep 15 '22 at 07:21
  • Thank you lol. i just changed it but it is still same.... – duststar0213 Sep 15 '22 at 07:33
  • Could you please provide a minimum reproducible example https://stackoverflow.com/help/minimal-reproducible-example – Aamir Sep 15 '22 at 07:39
  • To begin with, `test_A` in `TestB` is not the same as `test_A` in `test2.qml` (your ain window). On the other hand, when the user clicks, nothing changes in `TestB`. And you only received the message because you created two `TestA` objects. – SMR Sep 15 '22 at 11:56

1 Answers1

1

The only time that I see your resize function called is when you construct a TestA object. You're getting two printouts of "yes, resize is excuted" because you've created two instances of TestA. From the code you've shown, it will not execute that code when you click on TestB. There's plenty of ways to fix this. My recommendation is to remove references to TestA from inside TestB and handle all of their interactions within test2.qml. Also, you should automatically call resize whenever your ifSlected property changes.

TestA.qml:

Item {
    id: testA

    property bool ifSlected: false

    /* Automatically call resize when boolean value changes */
    onIfSlectedChanged: {
        ResizeRectScript.resize(testA.ifSlected, changedrect);
    }

    Rectangle {
        id: changedrect
        // ...
    }
}

TestB.qml:

Item {
    id: testB

      /* Don't create another instance of TestA here! */
//    TestA.TestA{
//        id: testA
//    }

    /* Create a signal to send up to the parent when clicked */
    signal clicked()

    Rectangle {
        id: myItem
        // ...
        MouseArea {
            anchors.fill: parent
            onClicked: {
                 /* We don't know anything about testA from inside testB */
//               testA.ifSlected = true;

                /* Just emit the signal */
                testB.clicked();
            }
        }
    }
}

test2.qml:

Window {
    // ...

    /* Now this is the only instance of TestA */
    TestA.TestA {
        id: test_A
    }

    TestB.TestB{
        id: test_B
        onClicked: {
            testA.ifSlected = true;
        }
    }
}
JarMan
  • 7,589
  • 1
  • 10
  • 25
  • Omg... this works!! Thank you so much, I've been stuck on this for 2 days. I have one last question. So right now TestB only have one child component (Rectangle, id: myItem) what if there are multiple child component. How do I refer their onClicked in main(test2.qml in this case) window? Thank you!! – duststar0213 Sep 15 '22 at 16:12
  • NVM. Just to answer this question. if there are two buttons (or ui elements) in TestB, just create two signals with different name and detect change in window – duststar0213 Sep 15 '22 at 16:32