How can I read listmodel role property in main.qml? - qt

In main.qml, I am updating listModel dynamically on every function addItem() call. Herein, I am setting two role; buttonTypeRole and source. OneText.qml file has a Text field. Actually, after inserting buttonTypeRole and source into listModel, I want to know whether source is being truncated or not.
IS ANY WAY TO READ OneText.qml TEXT TRUNCATED PROPERTY IN main.qml FILE?
main.qml
function additem()
{
listModel.insert(tlist.listModel.count , {"buttonTypeRole":"OneText.qml", "source":editText})
console.log("model-- "+tlist.listModel.get(sourceIndex).t)
}
listModel and ListView snapshot:
Item
{
property alias listModel: listModel
ListModel
{
id:listModel
}
Rectangle
{
id:listHolder
border.color: "transparent"
border.width: 3
color:"transparent"
height:560
width:600
focus:true
ListView
{
//id:listview
x:5
y:5
spacing:10
width:700
height:listHolder.height - 20
id:list
boundsBehavior: ListView.StopAtBounds
model:listModel
delegate:listComponent
clip: true
snapMode:ListView.SnapToItem
}
}
Component
{
id:listComponent
Rectangle
{
//color:"grey"
width:obj.width
height:obj.height
border.color: "red"
Loader
{
id:itemDisplay
source:buttonTypeRole
}
}
}
}
buttonTypeRole :OneText.qml snapshot
import QtQuick 2.0
import QtQuick.Controls 2.0
Item
{
id:one
height:obj.height
width:obj.width
Text
{
id:textOne
height:obj.height
width:obj.width
anchors.verticalCenter: parent.verticalCenter
verticalAlignment: "AlignVCenter"
anchors.leftMargin: 10
font.family: obj.fontFamily
font.bold: obj.fontBoldStyle == "true" ? true : false
font.pixelSize: obj.fontSize
text:source
elide: Text.ElideRight
}
}

Related

How to call data from elsewhere when I click a button in QML

When I click a button in QML, I want the data from another place that I created before to come to the textfields in my table, how can I do it? Can I do this in QML or do I need to create a separate backend cpp file? Can you help me please?
For example this below code is one row of my table
Rectangle{
border.width: 2
border.color: "black"
id:rectangle_mov_mean_nokta_sayisi
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: mainWindow.width/8
Layout.preferredHeight: mainWindow.height/22
Layout.margins: -3
Layout.fillWidth: true
color: row_even
Text{
color:normal_text
id:text_rectangle_mov_mean_nokta_sayisi
text:"Mov Mean Nokta Sayısı"
anchors.centerIn: parent
}
}
Rectangle{
border.width: 2
border.color: "black"
id:rectangle_mov_mean_nokta_sayisi_deger
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: mainWindow.width/8
Layout.preferredHeight: mainWindow.height/22
Layout.margins: -3
Layout.fillWidth: true
color:row_even
TextField {
id:textfield_rectangle_mov_mean_nokta_sayisi_deger
anchors.centerIn: parent
placeholderText: qsTr("")
color:normal_text
}
}
There are 20 of these rectangles. When I click a button, a separate value will be displayed for each text field. I need to create these values elsewhere.
you should read Signal and Slots in QML.
For example :
If you have 3 separate QML files:
In main.qml:
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("External Components with signals and slots")
Notifier{
id : notifierId
rectColor: "yellowgreen"
target: receiverId
}
Receiver {
id : receiverId
rectColor: "dodgerblue"
anchors.right: parent.right
}
Component.onCompleted: {
notifierId.notify.connect(receiverId.receiveInfo)//Connect signal to slot
}
}
and in Receiver.qml :
import QtQuick 2.12
Item {
property alias rectColor: receiverRectId.color
width: receiverRectId.width
height: receiverRectId.height
function receiveInfo( count){
receiverDisplayTextId.text = count
console.log("Receiver received number : "+ count)
}
Rectangle {
id : receiverRectId
width: 200
height: 200
color: "red"
Text {
id : receiverDisplayTextId
anchors.centerIn: parent
font.pointSize: 20
text : "0"
}
}
}
and in Notifier.qml:
import QtQuick 2.12
Item {
property alias rectColor: notifierRectId.color
width: notifierRectId.width
height: notifierRectId.height
property int count: 0
signal notify( string count)//Declare signal
property Receiver target : null
onTargetChanged: {
notify.connect(target.receiveInfo)
}
Rectangle {
id : notifierRectId
width: 200
height: 200
color: "red"
Text {
id : displayTextId
anchors.centerIn: parent
font.pointSize: 20
text : count
}
MouseArea{
anchors.fill: parent
onClicked: {
count++
notify(count)
}
}
}
}
you can see that by using signals and slots you can send data from Notifier.qml to Receiver.qml.

Displaying multiple images using QML in GridView

I've used the file dialog to select multiple images like this :
FileDialog{
id: uploadFiles
title: "Please choose images for dimple detection"
selectMultiple: true
nameFilters: [ "Image files (*.jpg *.png *.tif)", "All files (*)" ]
onAccepted: {}
}
I know I can reach the file paths using:
uplaodFile.fileUrls
but how can I display them in a Flickable item using GridView ?
Edit :
This the full code of the page ...
import QtQuick 2.15
import QtQuick.Controls 2.15
import "../controls"
import QtQuick.Dialogs 1.3
Item {
property bool isGridViewVisiable: false
Rectangle {
id: bgHome
color: "#2c313c"
anchors.fill: parent
Flickable{
id: flickableUpload
anchors.fill: parent
clip: true
Text {
id: titleResults
x: 249
width: 347
height: 141
color: "#ffffff"
text: qsTr("Upload the images to here please :)")
anchors.verticalCenter: parent.verticalCenter
anchors.top: parent.top
font.pixelSize: 25
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors.verticalCenterOffset: -110
anchors.horizontalCenterOffset: 8
anchors.topMargin: 59
anchors.horizontalCenter: parent.horizontalCenter
font.family: "Arial"
font.bold: true
minimumPointSize: 15
minimumPixelSize: 16
fontSizeMode: Text.Fit
}
UploadBtn{
id:uploadBtn
x: 285
y: 220
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
btnIconSource: "../../images/svg_images/upload-icon.svg"
onPressed: {
uploadFiles.open()
}
// opening a file dialog in order to upload the images
FileDialog{
id: uploadFiles
title: "Please choose images for dimple detection"
selectMultiple: true
nameFilters: [ "Image files (*.jpg *.png *.tif)", "All files (*)" ]
onAccepted: {
isGridViewVisiable = true
}
}
Component {
id: nameDelegate
Column {
Image {
id: delegateImage
anchors.horizontalCenter: delegateText.horizontalCenter
source: model; width: 256; height: 256; smooth: true
fillMode: Image.PreserveAspectFit
}
Text {
id: delegateText
text: model.name; font.pixelSize: 24
}
}
}
GridView{
id:gridView
visible: isGridViewVisiable
anchors.fill: parent
model:uploadFiles.fileUrls
delegate: nameDelegate
clip: true
}
}
ScrollBar.vertical: ScrollBar{}
}
}
This the full page that I will add to a content loader in the main qml file
PS:
the upload button is a customized button
uploadFiles.fileUrls is an array of filenames. So you can use that as a model for your GridView.
GridView {
model: uploadFiles.fileUrls
delegate: Image {
source: modelData
}
}
UPDATE:
It turns out there was a problem with my original answer, as well as with the code that you were trying.
First of all, you're making your GridView a child of your UploadBtn. Did you intend that? I think that will be too small of a space to draw your images.
But more importantly, the part that I was wrong about is that fileUrls is not an array of strings. It's a list<url>. I assumed QML would be smart enough to treat that the same as an array, or maybe implicitly convert it to an array if needed. But apparently I was wrong. So we'll just have to use it a little differently.
Flickable{
...
UploadBtn {
id:uploadBtn
...
FileDialog{
...
}
Component {
id: nameDelegate
Column {
Image {
...
// Access the list by index
source: uploadFiles.fileUrls[index]
}
Text {
...
text: uploadFiles.fileUrls[index]
}
}
}
}
// Move GridView outside of UploadBtn
GridView {
...
// Just use the length of the list as our model
model: uploadFiles.fileUrls.length
}
}

How to have a numerical model start at 1 in a combobox from QML

In the combobox from qml we can give them a model with a numerical value.
The options of the combobox then start from 0 to the model value minus 1.
What i want is to show the values on the combobox plus 1.
But still, if i try to access, with qml javascript, the value that is selected in that combobox is the original value, what i mean is, if it's the first option it's the value 0. The numbers shall only start from 1 in the display part of combobox.
I'm going to give an example (with a model=32):
display of the combobox
the options:
what i want is them to start at one, like this:
The code used was the following:
import QtQuick 2.9
import QtQuick.Controls 2.0
ApplicationWindow {
id: window
title: "Stack"
visible: true
height: 200
width: 400
Item {
id: page
anchors.fill: parent
width:parent.width
height: parent.height
Column{
width:parent.width
spacing:10
ComboBox {
id:comboBox
model: 32
objectName: "test"
implicitHeight: 30
displayText: currentText
// delegate:
// Button {
// id:buttonCombo
// width: parent.width
// text: index+1
// height:40
// contentItem: Text {
// text: buttonCombo.text
// font: comboBoxCustom.font
// leftPadding: 5
// horizontalAlignment: Text.AlignLeft
// verticalAlignment: Text.AlignVCenter
// elide: Text.ElideRight
// }
// background: Rectangle {
// color: buttonCombo.hovered ? (buttonCombo.pressed ? "#d8d8d8" : "#e8e8e8" ) : "#fff"
// }
// }
anchors.topMargin: 10
}
}
}
}
Maybe this could be done:
displayText: Number(currentText)+1
but i don't know if its the best solution...

QML ListView with sections representing first letter of model's name role - sections are not visible

I have QML ListView, which shows customers from database via UeCustomerModel. Customers are sorted in model via MySQL statement. All works fine, but now I want to add sections into ListView, so the customers are sorted in sections by first letter criteria. Here is my ListView:
ListView
{
id: ueCustomersListView
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignBottom
Layout.margins: 8
clip: true
spacing: 8
delegate: UeCustomerSelectorDelegate
{
ueParamWidth: ueCustomersListView.width
ueParamHeight: 128
ueParamImage: "image://ueCustomerModel/"+model.ueRoleImage
ueParamName: model.ueRoleCustomerName
ueParamTaxId: model.ueRoleCustomerTaxId
ueParamCurrentDebt: model.ueRoleCustomerCurrDebt
ueParamMaxDebt: model.ueRoleCustomerMaxDebt
} // delegate
section.property: model.ueRoleCustomerName // HERE RUNTIME ERROR OCCURS
section.criteria: ViewSection.FirstCharacter
section.delegate: UeCustomerSelectorSectionDelegate
{
ueParamWidth: ueCustomersListView.width
ueParamHeight: 128
ueParamName: section
} // section.delegate
Component.onCompleted:
{
model=ueCustomerModel;
} // Component.onCompleted
} // ListView
and here is section delegate:
import QtQuick 2.5
import QtQuick.Layouts 1.1
Rectangle
{
property int ueParamWidth
property int ueParamHeight
property string ueParamName
width: ueParamWidth
height: ueParamHeight
color: "#4682b4"
antialiasing: true
smooth: true
RowLayout
{
anchors.fill: parent
anchors.margins: 8
spacing: 8
Text
{
color: "#ffffff"
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
antialiasing: true
text: ueParamName
font.family: "Courier"
font.bold: true
font.pointSize: 12
clip: true
textFormat: Text.RichText
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
} // Text
} // RowLayout
} // Rectangle
Now, when ListView is shown, there are no sections visible. What did I miss, i.e., how do I correct section.property: model.ueRoleCustomerName statement to get alphabetical letters from customers (A, B, C, ...). I want ListView to section delegates according to Customer Name (delivered from database via model) first letter. Also, in mentioned line of code, I get QML runtime error Unable to assign [undefined] to QString. Why?
P.S.: model works perfectly (is fast, can search accross customers using TextField), I've tested it 5 times.
According to user sk2212's hint, I've upgraded the code with:
section.property: "ueParamName"
section.criteria: ViewSection.FirstCharacter
section.delegate: UeCustomerSelectorSectionDelegate
{
ueParamWidth: ueCustomersListView.width/2
ueParamHeight: ueCustomersListView.height/4
ueParamName: model.ueRoleCustomerName.subString(0,1)
} // section.delegate
and here is Section delegate:
import QtQuick 2.5
import QtQuick.Layouts 1.1
Rectangle
{
property int ueParamWidth
property int ueParamHeight
property string ueParamName
width: ueParamWidth
height: ueParamHeight
color: "#4682b4"
antialiasing: true
smooth: true
RowLayout
{
anchors.fill: parent
anchors.margins: 8
spacing: 8
Text
{
color: "#ffffff"
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
antialiasing: true
text: ueParamName
font.family: "Courier"
font.bold: true
font.pointSize: 12
clip: true
textFormat: Text.RichText
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
} // Text
} // RowLayout
} // Rectangle
Still does not work.
You have to use the section.property as a model data element:
delegate: UeCustomerSelectorDelegate
{
ueParamWidth: ueCustomersListView.width
ueParamHeight: 128
ueParamImage: "image://ueCustomerModel/"+model.ueRoleImage
ueParamName: model.ueRoleCustomerName
ueParamTaxId: model.ueRoleCustomerTaxId
ueParamCurrentDebt: model.ueRoleCustomerCurrDebt
ueParamMaxDebt: model.ueRoleCustomerMaxDebt
alphabet: model.ueRoleCustomerName.substring(0,1)
} // delegate
section.property: "alphabet"

How to apply Qt Graphical Effect on Delegate of Repeater in QML

I want to apply the QtGraphicalEffect ColorOverlay to an Image in a Repeater delegate. The problem is that I have to set the id of the Image as the source of the ColorOverlay, but I don't know the id, because it is dynamically created by the Repeater.
import QtQuick 2.4
import QtGraphicalEffects 1.0
Item {
id:mainItem
width: 800
height: 400
property string vorneColor: "red"
ListModel {
id: safeRailModel
ListElement {name: "vorne"; imageSource:"images/saferail/ring_vorne.png";}
ListElement {name: "vorneLinks"; imageSource:"images/saferail/ring_vorne_links.png"; }
}
Component {
id: imageDelegate
Image {
source: imageSource
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
fillMode: Image.PreserveAspectFit
opacity: 1
visible: true
}
}
Repeater {
id: safeRailRepeater
model: safeRailModel
delegate: imageDelegate
}
Component {
id: effectsDelegate
Item{
id:effectsItem
ColorOverlay {
anchors.fill: safeRailRepeater.itemAt(index)// <-- This doesn't work
source: safeRailRepeater.itemAt(index)// <-- This doesn't work
color: vorneColor
}
}
}
Repeater {
id: safeRailEffectsRepeater
model: safeRailModel
delegate: effectsDelegate
}
}
How can I set source and anchors.fill properties?
I searched everywhere, but I've only found something along the lines of safeRailRepeater.itemAt(index) or safeRailRepeater.itemAt(index).item but neither the former nor the latter works.
Side note: the ColorOverlay doesn't need to be in a seperate delegate and Repeater.
It would be great if somebody has a solution for this problem or could point me in the right direction.
Thank you very much!
The problem is that the itemAt() function call returns null because the other Repeater hasn't loaded its items yet. Also, the function call won't ever be reevaluated, because none of its arguments ever change, so you'll always get null.
The design is a bit odd though; I'd suggest moving the ColorOverlay into the same delegate, as you mentioned that it doesn't have to be in a separate Repeater:
import QtQuick 2.0
import QtQuick.Window 2.0
import QtGraphicalEffects 1.0
Window {
id: mainItem
width: 800
height: 400
visible: true
property string vorneColor: "red"
ListModel {
id: safeRailModel
ListElement { name: "vorne"; vorneColor: "salmon"; }
ListElement { name: "vorneLinks"; vorneColor: "steelblue"; }
}
Component {
id: imageDelegateComponent
Rectangle {
id: delegate
color: "grey"
opacity: 1
visible: true
width: 64
height: 64
layer.enabled: true
layer.effect: ColorOverlay {
color: vorneColor
}
}
}
Row {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
Repeater {
id: safeRailRepeater
model: safeRailModel
delegate: imageDelegateComponent
}
}
}
Using the layer API of Item is a convenient way of specifying graphical effects.
I also changed the Image to a Rectangle, since we don't have access to those images, and put the Repeater within a row, so that you can see all of the delegates.

Resources