I'm a QT newbie, i have learned to use grid view by connecting a list model. I want to limit the active viewing images to be just 4 instead of all the items in the list model
Rectangle {
id: Rect1;
width: 1280; height: 720;
ListModel {
id: listAssetModel
ListElement { Movie: "Arrow"; PosterURL: "posters/Arrow.jpg" }
ListElement { Movie: "Avatar"; PosterURL: "posters/Avatar.jpg" }
ListElement { Movie: "Avenge"; PosterURL: "posters/Avenge.jpg" }
ListElement { Movie: "Arrow"; PosterURL: "posters/Arrow.jpg" }
ListElement { Movie: "Avatar"; PosterURL: "posters/Avatar.jpg" }
ListElement { Movie: "Avenge"; PosterURL: "posters/Avenge.jpg" }
ListElement { Movie: "Arrow"; PosterURL: "posters/Arrow.jpg" }
ListElement { Movie: "Avatar"; PosterURL: "posters/Avatar.jpg" }
ListElement { Movie: "Avenge"; PosterURL: "posters/Avenge.jpg" }
}
GridView {
id: gridAssetPreview;
currentIndex: -1 // default - no focus on poster
x: 56; y: 189
width: 1140; height: 300
focus: true
cellWidth: 275; cellHeight: 300 // keeps the poster preview images aligned
highlight: appHighlight
model: listAssetModel
delegate: appDelegate
}
Component {
id: appDelegate
Item {
width: 250; height: 350 // controls the appHighlight size
Image {
id: imgPosterPreview
width: 225; height: 325
source: PosterURL
smooth: true
}
Text {
id: textAssetName
anchors { // draw this below and centre to the image
top: imgPosterPreview.bottom;
horizontalCenter: imgPosterPreview.horizontalCenter
}
text: AssetName
font.pointSize: 16
color:"white"
smooth: true
}
}
}
}
Grid view area is defined as below, but it seems on running it shows multiple rows of images which is not something i expect. I just want to see only 4 images in the whole 1280 x 720 screen.
width: 1140; height: 300
Please help, im stuck with this on my Sunday :-(
Add to your GridView:
flow: GridView.TopToBottom
Related
I am new to Qt. Wondering if there a possibility to make an item "unselectable" in ListView.
I see there are a lot of other things, e.g: collapsing , expanding, etc.
**
I have not find any simple example for this problem. **
Can you provide some minimalistic examples to make a specific item in the list unselectable?
I have the following minimalistic example. How can I set list item index 2 to be unselectable?
Window {
id: mainWindow
width: 130
height: 240
visible: truetitle: qsTr("Hello")
Rectangle {
id: bg
color: "#ffffff"
anchors.fill: parent
ListModel {
id: nameModel
ListElement { name: "Alice" }
ListElement { name: "Bob" }
ListElement { name: "Jay" }
ListElement { name: "Kate" }
}
Component {
id: nameDelegate
Text {
text: model.name
font.pixelSize: 24
}
}
ListView {
anchors.fill: parent
model: nameModel
delegate: nameDelegate
clip: true
highlight: Rectangle {
anchors { left: parent.left; right: parent.right }
//height: parent.height
color: "lightgrey"
}
}
}
}
I found numerous issues with your code snippet, so I attempted to address them all:
I made use of Page and set Page.background instead of declaring an outer Rectangle. This removes a level of indentation
I refactored NameComponent.qml to reduce the complexity of your main program
I change the delegate from Text to ItemDelegate so that it is clickable, and, it being clickable, I can (1) make the ListView have active focus so that it can receive keyboard events, (2) change the current item in the ListView => I think this achieves your criteria of being able to select a different item
I removed unnecessary anchoring from your highlight - your highlight will default anchor to your selected item
I set the width of your delegate to listView.width - I also made use of the ListView.view attached property so that your delegate and access properties from the ListView
Finally, I added a 20 pixel width vertical ScrollBar
import QtQuick
import QtQuick.Controls
Page {
background: Rectangle { color: "#ffffff" }
ListModel {
id: nameModel
ListElement { name: "Alice" }
ListElement { name: "Bob" }
ListElement { name: "Jay" }
ListElement { name: "Kate" }
}
ListView {
anchors.fill: parent
model: nameModel
delegate: NameDelegate { }
clip: true
highlight: Rectangle {
color: "lightgrey"
}
ScrollBar.vertical: ScrollBar {
width: 20
policy: ScrollBar.AlwaysOn
}
}
}
// NameDelegate.qml
import QtQuick
import QtQuick.Controls
ItemDelegate {
property ListView listView: ListView.view
width: listView.width - 20
text: model.name
font.pixelSize: 24
onClicked: {
listView.forceActiveFocus();
if (listView.currentIndex === index) {
listView.currentIndex = -1;
} else {
listView.currentIndex = index;
}
}
}
You can Try it Online!
I am trying to change scale property when I click on image, but I would like for it to change slowly. For now I have it instantly when I click on the image (the image gets bigger).
Here are my images:
Here I clicked on the first image and it is slightly bigger than the rest.
Here is my code:
width: 1920
height: 1080
visible: true
title: qsTr("Hello World")
color:'black'
XmlListModel {
id: xmlModel
source: "movies.xml"
query: "/Movies/Movie"
XmlRole { name: "id"; query: "id/string()" }
XmlRole { name: "name"; query: "name/string()" }
XmlRole { name: "year"; query: "year/number()" }
XmlRole { name: "rating"; query: "rating/string()" }
XmlRole { name: "path"; query: "path/string()" }
}
ScrollView{
width:parent.width
height: 400
clip: true
ListView {
id:list
spacing:20
width: parent.width; height: parent.width*0.5
anchors.verticalCenter: parent.verticalCenter
model: xmlModel
clip:true
orientation: ListView.Horizontal
delegate:
Rectangle{ id: rect; width: 300;height: 300; color:'gray'
Image{
id:id
anchors.fill: parent
source:path
fillMode: Image.PreserveAspectFit
scale:focus?1.2:1
MouseArea{
id:area1
width:parent.width
height: parent.height
anchors.fill:parent
Behavior on scale {
PropertyAnimation{ duration: 4000 }
}
onClicked: {
id.scale=1.2
}
//hoverEnabled: true
/*onEntered: {
// hobbit.scale=1.2
id.focus=true
}
onExited: {
// hobbit.scale=1
id.focus=false
}*/
}
}
So, in my code I have Behavior on scale part, but nothing changes. I tried different options and nothing. Any advice? Help would be greatly appreciated.
Move the Behavior object outside the MouseArea object.
Image {
id: img
scale: focus ? 1.2 : 1
Behavior on scale {
PropertyAnimation{ duration: 4000 }
}
MouseArea {
onClicked: {
img.scale = 1.2
}
}
}
I have a model (markerModel) derived from AbstractListModel which have three roles status, position and label. I am showing them by drawing circles on map. At the same time I want to print their position and label n a rectangle rectangle1. But MapItemView already have a delegate. Can there be multiple delegates with one model ?
Map {
id: map
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(22.5726, 88.3639)
zoomLevel: 14
MapItemView {
model: markerModel
delegate: markerDelegate
}
Component {
id: markerDelegate
MapQuickItem{
anchorPoint: Qt.point(2.5, 2.5)
coordinate: QtPositioning.coordinate(position.x, position.y)
zoomLevel: 0
sourceItem: Rectangle{
width: settings.marker_size;
height: settings.marker_size;
radius: settings.marker_size/2;
color: settings.marker_colors[status]
border.color: "white"
border.width: 1
}
}
}
}
Rectangle {
id: rectangle1
anchors.top: map.top
anchors.right: map.right
width: 500
height: 750
color: "#ffffff"
}
There is no direct connection between a model and a delegate, it is the view that connects the two.
You can have as many views using the same model for data source, and you can have whatever different delegates you want in each of those views:
ListModel {
id: mod
ListElement { value: "red" }
ListElement { value: "green" }
ListElement { value: "blue" }
ListElement { value: "cyan" }
ListElement { value: "magenta" }
}
Row {
ListView {
width: 100
height: 250
model: mod
delegate: Rectangle {
width: 100
height: 50
color: value
}
}
ListView {
width: 100
height: 250
model: mod
delegate: Rectangle {
width: 100
height: 50
color: "grey"
Text {
anchors.centerIn: parent
text: value
}
}
}
}
I wonder about the impact of having a component in a delegate of a ListView
Consider this:
DelegatePrototype.qml
MouseArea {
property Component myPage
onClicked: {
myPageLoader.sourceComponent = myPage
myPageLoader.pageData = model
}
}
and main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
ApplicationWindow {
id: appWindow
width: 1024
height: 800
visible: true
Loader {
id: myPageLoader
x: 100
active: true
property var pageData
}
Component {
id: myDelegate
DelegatePrototype {
width: 100
height: 50
myPage: Rectangle {
width: 400
height: 800
color: 'steelblue'
Column {
Text {
text: pageData.name
}
Row {
spacing: 4
Repeater {
model: pageData.age
delegate: Rectangle {
color: 'red'
width: 7
height: 30
}
}
}
}
}
Text {
anchors.centerIn: parent
text: model.name
}
}
}
ListView {
width: 100
height: 800
model: ListModel {
ListElement { name: 'Herbert'; age: 5 }
ListElement { name: 'Hans'; age: 3 }
ListElement { name: 'Ludwig'; age: 12 }
ListElement { name: 'Franz'; age: 9 }
ListElement { name: 'Peter'; age: 2 }
ListElement { name: 'Karl'; age: 15 }
}
delegate: myDelegate
}
}
So for the question: I have the property Component myPage in the DelegatePrototype and in main.qml I assign a component to it, that I declare on-the-fly.
I might have instead explicitly declared a component beforehand, and assigned it then like this:
Component {
id: myPageDelegate
Rectangle {
width: 400
height: 800
color: 'steelblue'
Column {
Text {
text: pageData.name
}
Row {
spacing: 4
Repeater {
model: pageData.age
delegate: Rectangle {
color: 'red'
width: 7
height: 30
}
}
}
}
}
}
Component {
id: myDelegate
DelegatePrototype {
width: 100
height: 50
myPage: myPageDelegate
Text {
anchors.centerIn: parent
text: model.name
}
}
}
While I belive in the latter case, I have only one Component-object for myPage in my memory, and for each of the instantiated DelegatePrototypes only a reference to this, I might imagine that in the former case it might happen that I create a Component-Object for myPage for each instance of DelegatePrototype, which might clutter the memory with identical Component-objects pretty fast.
Is my assumption right here and I should avoid assigning those on-the-fly-declarations of Components or will QML optimize this for me?
I know, there are crossfile-references (myPageLoader is referenced from the DelegatePrototype) but for the question I don't think it is necessary to explain why I chose to use this crossfile-reference.
How can i show text above gridview ?
I tried the following code but on scrolling , gridview elements come over the text and hide it . Even though I specified the width and height of gridview , gridview elements cross there bounds on scrolling . Any help is appreciated . Thanks .
Rectangle {
width: 300; height: 400
color: "gray"
ListModel {
id: appModel
ListElement { name: "Music"; icon: "pics/AudioPlayer_48.png" }
ListElement { name: "Movies"; icon: "pics/VideoPlayer_48.png" }
ListElement { name: "Camera"; icon: "pics/Camera_48.png" }
ListElement { name: "Calendar"; icon: "pics/DateBook_48.png" }
ListElement { name: "Messaging"; icon: "pics/EMail_48.png" }
ListElement { name: "Todo List"; icon: "pics/TodoList_48.png" }
ListElement { name: "Contacts"; icon: "pics/AddressBook_48.png" }
}
Component {
id: appDelegate
Item {
width: 100; height: 100
Image {
id: myIcon
y: 20; anchors.horizontalCenter: parent.horizontalCenter
source: icon
}
Text {
anchors { top: myIcon.bottom; horizontalCenter: parent.horizontalCenter }
text: name
}
}
}
Component {
id: appHighlight
Rectangle { width: 80; height: 80; color: "lightsteelblue" }
}
Text
{
id:txt
width: parent.width
height: 100
text: "8791561651"
}
GridView {
anchors.top:txt.bottom
height: 200
width: parent.width
cellWidth: 100; cellHeight: 100
highlight: appHighlight
focus: true
model: appModel
delegate: appDelegate
}
}
There are several way that you can try depending on exactly what you want to achieve:
Set clip property of the Gridview to true. This will prevent the view from going on top of other elements.
Put the Text element after the GridView element. This will make sure that the text is on top of the Gridview. If you do not set the clip however the gridview items will go below the text items.