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.
Related
working on an application using qml for the interface. I have a stack view in the main qml file which will push the qml file which will be a page to the stack view. Because there are multiple pages and buttons in these pages that when clicked may push a different page onto the stack view, I created a function in the main qml file which i will call from the pages when buttons are clicke. The pages folder which contain many different pages is a subdirectory of main.qml folder. The functionis supposed to push the pages unto the stack view. However, on click of the button, the satck view does not push the new page.
This is the code below
main qml file
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import "pages"
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
property url source: ""
function changeView(source){
stackView.push(Qt.resolvedUrl(source))
}
Rectangle {
id: rectangle
color: "#391199"
anchors.fill: parent
StackView {
id: stackView
anchors.fill: parent
initialItem: Qt.resolvedUrl("pages/homepage.qml")
}
}
}
/*##^##
Designer {
D{i:0;formeditorZoom:0.75}
}
##^##*/
homePage.qml
import QtQuick 2.0
import QtQuick.Controls 2.15
import "qrc:../main.qml" as Main
Item {
Rectangle {
id: rectangle
color: "#08630f"
anchors.fill: parent
Button {
id: button
x: 478
y: 255
text: qsTr("Change ")
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: 10
anchors.bottomMargin: 10
onClicked: {
source = "pages/nextPage.qml"
Main.changeView(source)
}
}
}
}
nextPage.qml
import QtQuick 2.0
import QtQuick.Controls 2.15
import "../main.qml" as Main
Item {
Rectangle {
id: rectangle
color: "#08404b"
anchors.fill: parent
Button {
id: button
x: 478
y: 255
text: qsTr("Change ")
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: 10
anchors.bottomMargin: 10
onClicked: {
Main.changeView("pages/homePage.qml")
}
}
}
}
I suspect the problem is coming from the calling of the function but i have a little expertise in qml. I get this error: Property 'changeView' of object [object Object] is not a function
You will want to call the changeView function on the actual main window, not on the import.
This involves a bit of "magic", you can give the main Window an id, which will be available in all the children of it (so, magic because if looking at a single page file, you can wonder what that id is doing there). So, make sure to pick a wise name which won't collide with other id (i.e. root would be quite bad)
//main.qml
Window {
id: main_window
function changeView(source) { ... }
}
//homePage.qml
Item {
...
Button {
...
onClicked: main_window.changeView("pages/nextPage.qml")
}
}
For my Custom window, shown in the answer, I've created a Component named PathButton
import QtQuick 2.0
import QtQuick.Shapes 1.12
Item {
property alias pathData: svg.path
width: 24
height: 24
Shape {
ShapePath {
fillColor: "black"
PathSvg {
id: svg
path: pathData
}
}
}
}
and used it to minimize, maximize and close the window like this:
RowLayout{
Layout.preferredWidth: 100
anchors.right: title.right
PathButton{
pathData: ViewModel.minimizeIcon
MouseArea{
anchors.fill: parent
onClicked: mainWindow.showMinimized()
}
}
PathButton{
pathData: ViewModel.maximizeIcon
MouseArea{
anchors.fill: parent
//this doesn't restore the window to its Normal state, showMaximized() is called always
onClicked: mainWindow.Maximized? mainWindow.showNormal() : mainWindow.showMaximized()
}
}
PathButton{
pathData: ViewModel.closeIcon
MouseArea{
anchors.fill: parent
onClicked: mainWindow.close()
}
}
}
in all those I've a MouseArea. What I want is to have that MouseArea in my Custom Component and declare a property of type eventhandler/signal/slot and assign that handler for onClicked like this:
import QtQuick 2.0
import QtQuick.Shapes 1.12
Item {
property alias pathData: svg.path
property alias handler: mouse.onClicked
width: 24
height: 24
Shape {
ShapePath {
fillColor: "black"
PathSvg {
id: svg
path: pathData
}
}
}
MouseArea{
id: mouse
anchors.fill: parent
onClicked: handler
}
}
and in its usage I want to assign the relevant function like this:
PathButton{
pathData: ViewModel.minimizeIcon
handler: mainWindow.showMinimized()
}
EDIT
Here's what I've in PathButton.qml:
import QtQuick 2.0
import QtQuick.Shapes 1.12
Item {
id: root
property alias pathData: svg.path
signal onClicked()
width: 24
height: 24
Shape {
ShapePath {
fillColor: "black"
PathSvg {
id: svg
path: pathData
}
}
}
MouseArea{
anchors.fill: parent
onClicked: root.onClicked()
}
}
and in main.qml I get that error and when I hit run with that error, in Application Output I get another error:
I think what you're looking for is simply a signal:
// PathButton.qml
Item {
id: root
signal clicked()
...
MouseArea {
onClicked: root.clicked()
}
}
Then you would use it like this:
PathButton {
onClicked: mainWindow.showMinimized()
}
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;
}
}
}
}
}
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
I have QT 5.5 and it won't support SwipeView. I tried doing with listView but I am not getting what I expected. I want a similar functionality code in QT 5.5 like the code given below which is written in QT 5.6. Please help
import QtQuick 2.6
import QtQuick.Controls 2.0
import QtQuick.Window 2.0
Window {
visible: true
width: 200
height: 400
title: qsTr("Hello World")
id: page
SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: 0
Page {
Label {
text: qsTr("First page")
anchors.centerIn: parent
}
}
Page {
Label {
text: qsTr("Second page")
anchors.centerIn: parent
}
}
Page {
Label {
text: qsTr("Third page")
anchors.centerIn: parent
}
}
Page {
Label {
text: qsTr("Fourth page")
anchors.centerIn: parent
}
}
Page {
Label {
text: qsTr("Fifth page")
anchors.centerIn: parent
}
}
}
Rectangle
{
id:minus
width:parent.width/2
height:100
anchors.left:parent.left
anchors.bottom:parent.bottom
color:"red"
MouseArea
{
anchors.fill:parent
onClicked:{
if(swipeView.currentIndex>0)
swipeView.currentIndex--
}
}
}
Rectangle
{
id:plus
width:parent.width/2
height:100
anchors.right:parent.right
anchors.bottom:parent.bottom
color:"green"
MouseArea
{
anchors.fill:parent
onClicked:{
if(swipeView.currentIndex<4)
swipeView.currentIndex++
}
}
}
}
If you cannot update your Qt version, you can indeed approximate a SwipeView using a ListView, a VisualItemModel, and a default qml property.
SwipeView.qml
ListView
{
id: root
// Allow to add pages as you would for a QtQuick.Controls 2 SwipeView
// Each item you declare in your SwipeView will be reparented to itemModel
default property alias items: itemModel.children
// SwipeView is horizontal
orientation: Qt.Horizontal
// Hide out of bounds pages
clip: true
// Do not stop between two pages
snapMode: ListView.SnapToItem
// Update currentIndex as you swipe through the pages
highlightRangeMode: ListView.StrictlyEnforceRange
model: VisualItemModel {
id: itemModel
// Used to bind the pages size to the swipeView size
onChildrenChanged: {
for(var i=0;i<children.length; i++)
{
children[i].width = Qt.binding(function(){return root.width})
children[i].height = Qt.binding(function(){return root.height})
}
}
}
}
Page.qml
Item {
property string title
Rectangle
{
anchors.fill: parent
border.width: 1
}
Text
{
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 20
text: title
}
}
PageIndicator.qml
Row
{
id: root
property int count
property int currentIndex
property Component delegate: bullet
property bool interactive
spacing: 5
Component
{
id: bullet
Rectangle
{
height: 10
width: height
radius: height/2
color:"black"
opacity: currentIndex==index?0.8:0.2
}
}
Repeater
{
model: root.count
Loader
{
property int index: model.index
sourceComponent: delegate
}
}
}
main.qml
import QtQuick 2.5
import QtQuick.Controls 1.4
ApplicationWindow
{
id: window
visible: true
width: 300
height: 300
SwipeView
{
id: swipeView
anchors.fill: parent
Page
{
title: "Page 1"
}
Page
{
title: "Page 2"
}
Page
{
title: "Page 3"
}
}
PageIndicator
{
id: pageIndicator
anchors.bottom: swipeView.bottom
anchors.bottomMargin: 10
anchors.horizontalCenter: swipeView.horizontalCenter
count: swipeView.count
currentIndex: swipeView.currentIndex
}
}
Qt Quick Controls 2 was introduced in Qt 5.7:
Qt Quick Controls 2 provides a set of controls that can be used to build complete interfaces in Qt Quick. The module was introduced in Qt 5.7.
Qt Labs Controls was introduced in Qt 5.6, so the code that you referenced would have to use the Qt.labs.controls 1.0 import in order to run with Qt 5.6.
You need to use a newer Qt version (5.6 or newer).