javascriptc++qtqmlqqmlcomponent

Use button from a qml to control(interact) the size of Rectangle which is in another qml file [QML] [JS]


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!!


Solution

  • 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;
            }
        }
    }