QML reference errors - qt

I have a small QML-project and I'm facing a problem with qml component references. So I'm trying to start the NumComponent.qml's numberTimer from startButton in the main.qml.
main.qml
import QtQuick 2.7
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
NumComponent{} //my component written in NumComponent.qml
Rectangle{
id: startButton
anchors.centerIn: parent
height: parent.height * 0.2
width: height
color: "lightblue"
MouseArea{
anchors.fill: parent
onClicked: {
numberTimer.start();
}
}
}
}
NumComponent.qml
import QtQuick 2.0
Rectangle {
id: numberRect
color: "red"
height: parent.height * 0.4
width: height
Text{
id: numberText
anchors.centerIn: parent
text: ""
}
Timer{
id: numberTimer
interval: 100
repeat: true
onTriggered: {
numberText.text = Math.floor(Math.random() * 8);
}
}
}
I get this error: "qrc:/main.qml:22: ReferenceError: numberRect is not defined"

Give your NumComponent in main.qml an id:
NumComponent{
id: numComponent
} //my component written in NumComponent.qml
change your onClicked handler to:
numComponent.startTimer();
Another variant:
Add to your numberRect a property alias:
property alias timed: numberTimer.running
Change you onClicked handler in main to:
numComponent.timed = !numComponent.timed;
Add to your NumComponent.qml in your root item:
function startTimer() {
numberTimer.start();
}
Now you can start and stop your timer.

Related

TableView QML Type onClicked event

I am currently using a TableView in my QML file. I would like to know which cell the user clicked.. There is a post here: https://forum.qt.io/topic/84284/tableview-onclicked-slot/2 which shows the onClicked code in the QML file. However, when i tried on my code it says invalid property name. My QML file code is:
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import TransactionHistoryTableModel 1.0
import tech.siotgov.DataManager 1.0
import "../../components" as Components
import "../../utils/httpRequest.js" as HttpRequest
Rectangle {
id: root
objectName: "TransactionHistory"
color: "white"
property string pageTitle: "Transaction History"
ColumnLayout {
id: home
anchors.leftMargin: parent.width * 0.05
anchors.rightMargin: parent.width * 0.05
anchors.fill: parent
anchors.horizontalCenter: parent.horizontalCenter
Components.PageTitle {
title: pageTitle
}
Rectangle {
id: transactionHistoryDisplay
color: "white"
Layout.fillWidth: true
Layout.preferredHeight: parent.height - 100
Components.Table {
model: _transactionHistoryTableModelAPI
columnWidths: [0.4, 0.6]
onClicked: {
console.log(" click ")
console.log(color_string)
}
}
}
Item { //spacer
Layout.fillWidth: true
Layout.fillHeight: true
Rectangle {
anchors.fill: parent
color: "white"
}
}
}
Component.onCompleted: {
const locationId = DataManager.currentLocation.locationId;
const d = new Date()
d.setTime(d.getTime() - d.getTimezoneOffset()*60*1000);
const datetimeStamp = d.toISOString().split('.')[0]
_transactionHistoryTableModelAPI.resetTable(locationId);
HttpRequest.query(
"query { transactionsByLocation(fromDateTime:\"2019-01-01T07:54:34\", toDateTime:\"" + datetimeStamp + "\", location:" + locationId + ") { transactionId, datetime, items { transactionItemId }, transactionType {name}, location_1{locationName}, location_2{locationName} } }",
res => {
_transactionHistoryTableModelAPI.updateTable(res.data.transactionsByLocation);
})
}
}
The Table.qml file is:
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
TableView {
anchors.fill: parent
clip: true
property var columnWidths: [0.5, 0.5] // as fractions of parent width
// preferably overwrite this when using
columnWidthProvider: function (column) { return Math.max(parent.width * columnWidths[column], 1) }
delegate: Rectangle {
implicitHeight: text.implicitHeight
border.color: "#dddddd"
color: (heading==true)?"#dddddd":"white"
Text {
id: text
text: tabledata
width: parent.width
wrapMode: Text.Wrap
padding: 5
}
}
}
In a view you must set the MouseArea in the delegate and expose it through a signal from the root of the component:
Table.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
TableView {
id: root
anchors.fill: parent
clip: true
signal clicked(int row, int column) // <---
property var columnWidths: [0.5, 0.5] // as fractions of parent width
// preferably overwrite this when using
columnWidthProvider: function (column) { return Math.max(parent.width * columnWidths[column], 1) }
delegate: Rectangle {
implicitHeight: text.implicitHeight
border.color: "#dddddd"
color: heading ? "#dddddd" : "white"
Text {
id: text
text: tabledata
width: parent.width
wrapMode: Text.Wrap
padding: 5
}
MouseArea{
anchors.fill: parent
onClicked: root.clicked(model.row, model.column) // <---
}
}
}
*.qml
// ...
Components.Table {
model: _transactionHistoryTableModelAPI
columnWidths: [0.4, 0.6]
onClicked: console.log(row, column)
}
// ...

Can't bind on current item in QML view/model

I have a simple task: need to output some information about current item of ListView separately. For example, in outside Label, but I can't succeed.
I figured out that problem related to where model was defined. If it is separate object with id this behavior happened. But when I define it inlined inside the view, all works fine. This behaviour is very weird and looks like a bug.
To make this code work, just switch to commented model definition. Anybody encounter this problem or may be know something?
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import Qt.labs.calendar 1.0
ApplicationWindow {
title: qsTr("Hello World")
width: 640
height: 480
visible: true
CalendarModel {
id: myModel
from: new Date(2018, 0, 1)
to: new Date(2018, 11, 31)
}
ColumnLayout {
anchors.fill: parent
Label {
id: myLabel
text: "myLabel1"
}
Label {
text: myModel.monthAt(myView.currentIndex)
}
ListView {
id: myView
Layout.fillWidth: true
Layout.fillHeight: true
snapMode: ListView.SnapOneItem
orientation: ListView.Horizontal
highlightRangeMode: ListView.StrictlyEnforceRange
boundsBehavior: Flickable.StopAtBounds
model: myModel
// model: CalendarModel {
// id: myModel
// from: new Date(2018, 0, 1)
// to: new Date(2018, 11, 31)
// }
delegate: Rectangle {
color: "green"
width: myView.width
height: 200
Text {
anchors.centerIn: parent
text: model.month
}
}
onCurrentIndexChanged: {
console.log(currentIndex)
myLabel.text = String(currentIndex)
}
ScrollIndicator.horizontal: ScrollIndicator {}
}
}
}

How to implement swipeview QtQuick 2.5

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).

Multi item swipedelegate

Edited due to insufficient intial posting.
Hi,
thanks for your help!
You're right, I guess it is better to include the whole file, in spite of the size:
import QtQuick 2.5
import QtQuick.LocalStorage 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Controls 2.1
import QtQuick.Controls.Styles 1.4
import QtQuick.Window 2.0
import QtQuick.Controls.Material 2.1
import "./database.js" as Database
ApplicationWindow {
visible: true
width: 640
height: 480
id: appWindow
x: Screen.width / 2 - width / 2
y: Screen.height / 2 - height / 2
title: qsTr("Project Stats")
Material.theme: Material.Dark
ListModel {
id: projectModel
ListElement {
projectID: "123654"
manager: "Schneider"
sponsor: "3466"
}
}
Component {
id: projectDelegate
SwipeDelegate {
id: projectSwipeDelegate
width: parent.width
height: projectDelegateItem.implicitHeight
anchors.horizontalCenter: parent.horizontalCenter
spacing: 10
contentItem: Item {
id: projectDelegateItem
Text {
id: projectID_text
text: "Project ID: " + projectID
font.pointSize: 20
anchors.horizontalCenter: parent.horizontalCenter
font.weight: Font.Black
color: "white"
}
Text {
id: manager_text
text: 'Manager: ' + manager + " Sponsor: " + sponsor
anchors.top: projectID_text.bottom
anchors.horizontalCenter: parent.horizontalCenter
font.weight: Font.Thin
color: "lightgrey"
}
}
onClicked: {
console.log(index, projectModel.get(index).projectID)
if (swipe.complete)
projectModel.remove(index)
else {
//var component= Qt.createComponent("timepointsstackview.qml")
//var loadwin = component.createObject(appWindow)
//loadwin.selected_project = projectModel.get(index).projectID
// stackView.push(Qt.resolvedUrl("timepointsstackview.qml"), {properties: {selected_project: projectModel.get(index).projectID}})
stackView.push(component, {properties: {selected_project: projectModel.get(index).projectID}})
}
}
swipe.right: Label {
id: deleteLabel
text: qsTr("Delete")
color: "white"
verticalAlignment: Label.AlignVCenter
padding: 12
height: parent.height
anchors.right: parent.right
SwipeDelegate.onClicked: projectListView.model.remove(index)
background: Rectangle {
color: deleteLabel.SwipeDelegate.pressed ? Qt.darker("tomato", 1.1) : "tomato"
}
}
}
}
Item {
Component.onCompleted: {
Database.getDatabase()
Database.getProjects()
}
}
StackView {
id: stackView
anchors.fill: parent
// Implements back key navigation
focus: true
Keys.onReleased: if (event.key === Qt.Key_Back && stackView.depth > 1) {
stackView.pop();
event.accepted = true;
}
initialItem: Item {
width: parent.width
height: parent.height
ListView {
id: projectListView
anchors.fill: parent
clip: true
model: projectModel
delegate: projectDelegate
}
}
}
onClosing: {
if (Qt.platform.os == "android") {
close.accepted = false;
// if (stack.depth > 1) stack.pop();
}
}
}
Meanwhile I already had removed the row/column stuff, which I put in to get it working somehow though I started without it.
I also experimented with implicitheight before intially posting, but sadly to no avail. The above is my current code, though putting in
height: projectDelegateItem.implicitHeight
in that spot (probabaly not the correct one or the wrong reference? Had to change it from your suggestion as I already took out the row) leads to rendering in one spot only.
Thanks for your time so far and also if you still have the patience to give me a clue where to turn the screws...
Ok, first of all:
Take warnings serious. If qml tells you, you should not try to use anchors within rows or columns, don't do it!
QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row. Row will not function.
QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column. Column will not function.
Also don't do it, if you can't see those warnings. It will mess up a lot.
A row automatically anchors all its children side by side to each other. A column does the same, just horizontraly. If you mess with it, everything breaks.
Frankly: I don't even understand why you use this strange Row/Column-Setup.
For your case it seems way better to just resort to anchoring. If you have reasons for that, why not take a grid?
Secondly: You need to specify a height for your delegate. Unfortunately it seems like, it does not calculate an implicit height.
The SwipeDelegate calculates its own implcitHeight based on the implicitHeight of its contentItem.
The problem is, that you don't assign the row (which has a proper implicitHeight) as the contentItem, but add it as a child instead.
Assigning it as contentItem would fix that for you.
Regarding your edit, and removal of the Row: The Item you use now does not calculate a implicitHeight based on its children. So you need to provide your calculation yourself.
This will set a proper height to your delegate, and your delegates won't overlap.
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 2.0
Window {
width: 1024
height: 800
visible: true
ListView {
width: 400
height: 800
model: ListModel {
ListElement { projectID: 0; manager: 'I'; sponsor: 'mom' }
ListElement { projectID: 1; manager: 'YOU'; sponsor: 'dad' }
ListElement { projectID: 1; manager: 'HE'; sponsor: 'auntie' }
}
delegate: SwipeDelegate {
id: projectSwipeDelegate
width: parent.width
// height: <--- provide a height, if the contentItem does not provide it.
contentItem: Row{ // <--- Add your content as contentItem.
id: rowProjectDelegate
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width
Column {
id: column
// anchors.horizontalCenter: parent.horizontalCenter <--- Don't do that!
width: parent.width
Rectangle{ // If you don't want to have them in a column, they can't be siblings. If you want to, then you should.
height: 10
width: 250
color: "red"
Rectangle {
height: 10
width: 200
color: "blue"
}
}
Label {
id: projectID_text
text: "Project ID: " + projectID
font.pointSize: 20
font.weight: Font.Black
color: "white"
}
Label {
id: manager_text
text: 'Manager: ' + manager + " Sponsor: " + sponsor
// anchors.top: projectID_text.bottom <--- Don't do that!
font.weight: Font.Thin
color: "lightgrey"
}
}
}
}
}
}

Qt - change property from a component in a different qml file

Update 1
The idea is to be able to change the front and back of CardForm from main.qml because i want to be able to use multiple CardForm instances. I tried to do what they did here but it doesnt work.
Here is the code:
CardForm.qml
import QtQuick 2.0
Flipable {
id: sCard
width: 75
height: 200
property bool flipped: false
property string front: "Front"
property string back: "Back"
property alias callFront : front
property alias callBack : back
front: Rectangle{
id: front
anchors.fill: sCard
border.width: 2
border.color: "black"
radius: 5
Text{
anchors.centerIn: parent
text: sCard.front
}
}
back: Column{
Rectangle{
id: back
anchors.fill: sCard
radius: 5
border.width: 2
border.color: "black"
Text{
anchors.centerIn: parent
text: sCard.front
}
Text{
anchors.centerIn: parent
text: sCard.front
}
}
}
transform: Rotation{
id: flip
origin.x: sCard.width
origin.y: sCard.height/2
axis.x: 0; axis.y: 1; axis.z: 0 // set axis.y to 1 to rotate around y-axis
angle: 0 // the default angle
}
states: State {
name: "back"
PropertyChanges {
target: flip
angle: 180
}
when: sCard.flipped
}
transitions: Transition{
NumberAnimation {
target: flip
property: "angle"
duration: 200
}
}
MouseArea{
anchors.fill: parent
onClicked: sCard.flipped = !sCard.flipped
}
}
main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Neuro Seed")
SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: tabBar.currentIndex
Column {
CardForm{
id: test
anchors.centerIn: parent
test.callFront: "Hello World!"
test.callBack: "Bonjour le Monde!
}
}
}
}
Here are the error messages:
SHGetSpecialFolderPath() failed for standard location "Shared Configuration", clsid=0x1c. ()
qrc:/main.qml:17:13: QML CardForm: back is a write-once property
qrc:/main.qml:17:13: QML CardForm: front is a write-once property
qrc:/main.qml:16:9: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column. Column will not function.
the c1.getFront() and getBack() were from a C++ class that I made. I changed these to "Hello World!" and "Bonjour le Monde!"
So after many hours of struggling I figured out that to create a property which is accessible by other .qml files you must create a property alias name: id.property. The id must point towards an existing instance of a object in your code and the property of this instance that you wish to be able to change from the outside. So in my case it would be like so:
CardForm.qml
Flipable {
id: sCard
width: 75
height: 200
property bool flipped: false
property alias frontText : front.text
front: Rectangle{
id: front
anchors.fill: sCard
border.width: 2
border.color: "black"
radius: 5
Text{
anchors.centerIn: parent
text: frontText
}
}
}
and in the main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Neuro Seed")
Rectangle {
anchors.fill: parent
CardForm{
id: test
anchors.centerIn: parent
frontText: "Hello World!"
}
}
}
}

Resources