Hi I want to put this code :
highlight: Rectangle {
color: "black"
radius: 5
opacity: 0.7
focus: true
}
into mouseArea in onclick handler:
MouseArea {
id: mouse_area1
z: 1
hoverEnabled: false
anchors.fill: parent
onClicked: {
}
This is all listView:
ListView {
id: listview1
x: 0
y: 82
// width: 574
// height: 967
width: window.width
height: window.height
visible: true
keyNavigationWraps: false
boundsBehavior: Flickable.DragAndOvershootBounds
opacity: 1
maximumFlickVelocity: 2500
anchors.leftMargin: 0
highlightMoveSpeed: 489
contentWidth: 0
preferredHighlightEnd: 2
spacing: 5
highlightRangeMode: ListView.NoHighlightRange
snapMode: ListView.SnapToItem
anchors.bottomMargin: 0
anchors.rightMargin: 0
anchors.topMargin: 82
anchors.fill: parent
model: myModel
delegate:Component {
//id: contactDelegate
Item {
property variant myData: model
width: 574; height: 90
Column {
x: 12
y: 0
width: 562
height: 90
anchors.rightMargin: 0
anchors.bottomMargin: 0
anchors.leftMargin: 12
anchors.topMargin: 0
anchors.fill: parent
spacing: 2
Text { text: '<b>ID: </b> ' + id_user ; verticalAlignment: Text.AlignTop; wrapMode: Text.NoWrap; horizontalAlignment: Text.AlignHCenter; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 10 }
Text { text: '<b>Name: </b> ' + user_name; horizontalAlignment: Text.AlignHCenter; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 10 }
Text { text: '<b>Lastname: </b> ' + user_lastname; horizontalAlignment: Text.AlignHCenter; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 10 }
Text { height: 16; text: '<b>Tel number: </b> ' + user_number; verticalAlignment: Text.AlignVCenter; horizontalAlignment: Text.AlignHCenter; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 10 }
Text { text: '<b>Address: </b> ' + user address; horizontalAlignment: Text.AlignHCenter; color:"steelblue"; font.family: "Helvetica"; font.pointSize: 10 }
MouseArea {
id: mouse_area1
z: 1
hoverEnabled: false
anchors.fill: parent
onClicked:
Item
{
}
}
}
}
}
//delegate: contactDelegate
highlight: Rectangle
{
color:"black"
radius: 5
opacity: 0.7
focus: true
}
}
For now highlight is working only when using arrows, bbut this will be app for android so I need on touch that same effect, and SECOND question is how to read certain data from selected item in listview?
Inside I have like id,name,lastname,number and adress.
I want to put those values into text_input boxes.
Thank you
It appears you need two solutions to your question:
You want to be able to set the current item of the ListView when it's clicked
You want to be able to know when the current selection changes
The Qt5 documentation says this about ListView mouse and touch handling:
The views handle dragging and flicking of their content, however they do not handle touch interaction with the individual delegates. In order for the delegates to react to touch input, e.g. to set the currentIndex, a MouseArea with the appropriate touch handling logic must be provided by the delegate.
Key input will work out-of-the-box but you'll need to explicitly catch the mouse/touch event on the delegate, and change the ListView.currentIndex value based on the index value of the selected delegate item.
Here's a full example:
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
width: 640
height: 480
visible: true
ListModel {
id: model
ListElement {
name:'abc'
number:'123'
}
ListElement {
name:'efg'
number:'456'
}
ListElement {
name:'xyz'
number:'789'
}
}
ListView {
id: list
anchors.fill: parent
model: model
delegate: Component {
Item {
width: parent.width
height: 40
Column {
Text { text: 'Name:' + name }
Text { text: 'Number:' + number }
}
MouseArea {
anchors.fill: parent
onClicked: list.currentIndex = index
}
}
}
highlight: Rectangle {
color: 'grey'
Text {
anchors.centerIn: parent
text: 'Hello ' + model.get(list.currentIndex).name
color: 'white'
}
}
focus: true
onCurrentItemChanged: console.log(model.get(list.currentIndex).name + ' selected')
}
}
It does the following things:
creates a simple list and model
uses a MouseArea item within the item delegate to update set the list.currentIndex = index which is a local var and unique to the selected item
listens for the onCurrentItemChanged event of the ListView to show how to access the current model item values
binds the text value of the currently selected item to the highlight item to show using the currently selected values elsewhere
Answer provided by denoth: You need to add this line:
listview1.currentIndex = index
ListView provides so called "attached properties", i.e. properties available in the delegate for the list. Among them Listview.view is a reference to the list itself. It can be used to access currentIndex property and update it. Hence, to solve your issue just:
Uncomment //id: contactDelegate.
Set contactDelegate.ListView.view.currentIndex = index in the
OnClick even handler.
For those who use highlighting on a ListView with a specific height (being: not 100% height filled):
Be sure to enable the clip property of the ListView, as else the highlight will still be visible outside the ListView's borders while scrolling.
ListView
{
clip: true
}
As discussed here:
Hide the highlight of a ListView while scrolling
Simplest than ever, you can use: onCurrentItemChanged
ListView{
id: listViewMainMenu
signal Myselect(int playmode)
onCurrentItemChanged: {
Myselect(listViewMainMenu.currentIndex)
console.log("index changed see this " + currentIndex)
}
// ...
}
// do not forget to connect to this signal
otheritem.connect(thisitem.Myselect) //used in drag and works also with pathview
The answer is indeed listView.currentIndex = index.
Whilst playing around with this answer, I found that the ListView may not have keyboard focus, so, I found it may be necessary to call listView.forceActiveFocus() so that up and down arrow key presses are handled.
I found the delegate, particularly the usage of Text in the ListView delegate to be verbose and cumbersome. To clean that up, I refactored an AppInfo component for rendering the contact in a nice manner.
To polish the answer, I provided some sample data for the contacts ListModel and cleaned up the highlight mechanism:
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
ListView {
id: listView
anchors.fill: parent
model: contacts
clip: true
focus: true
delegate: Item {
width: frame.width
height: frame.height
Frame {
id: frame
background: Item { }
ColumnLayout {
id: columnLayout
AppInfo { label: "ID"; value: id_user }
AppInfo { label: "Name"; value: user_name }
AppInfo { label: "Last Name"; value: user_lastname }
AppInfo { label: "Tel number"; value: user_number }
AppInfo { label: "Address"; value: user_address }
}
}
MouseArea {
anchors.fill: parent
onClicked: {
listView.currentIndex = index;
listView.forceActiveFocus();
}
}
}
highlight: Rectangle {
border.color: "black"
radius: 5
opacity: 0.7
focus: true
}
}
ListModel {
id: contacts
ListElement {
id_user: "bgates"
user_name: "Bill"
user_lastname: "Gates"
user_number: "555-Microsoft"
user_address: "1 Microsoft Way"
}
ListElement {
id_user: "sjobs"
user_name: "Steve"
user_lastname: "Jobs"
user_number: "555-Apple"
user_address: "1 Apple St"
}
ListElement {
id_user: "jbezos"
user_name: "Jeff"
user_lastname: "Bezos"
user_number: "555-Amazon"
user_address: "1 Amazon Ave"
}
}
}
//AppInfo.qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
RowLayout {
property string label: "ID"
property string value: "id"
Text {
Layout.preferredWidth: 100
text: label
verticalAlignment: Text.AlignTop
wrapMode: Text.NoWrap
horizontalAlignment: Text.AlignRight
color: "steelblue"
font.family: "Helvetica"
font.pointSize: 10
font.bold: true
}
Text {
Layout.preferredWidth: 100
text: value
verticalAlignment: Text.AlignTop
wrapMode: Text.NoWrap
horizontalAlignment: Text.AlignLeft
font.family: "Helvetica"
font.pointSize: 10
}
}
You can Try it Online!
There's ItemDelegate since Qt 5.7. It reacts to mouse clicks by default.
import QtQuick
import QtQuick.Controls
ListView {
model: ListModel {
ListElement {
name: "Item 1"
}
ListElement {
name: "Item 2"
}
ListElement {
name: "Item 3"
}
}
delegate: ItemDelegate {
text: name
}
}
Related
I have below stack of components and I want to read and set value of the TextFiled:
-Rectangle
-----TabView
---------Tab
-----------Rectangle
--------------GridLayout
------------------Rectangle
--------------------TextField <--- I want to access this TextField
I have also a case where I need to access Repeater inside the Tab:
-Rectangle
-----TabView
---------Tab
-----------Rectangle
--------------GridLayout
------------------Repeater
--------------------TextField <--- I want to access this TextField also
I have tried to access it using:
var tab0 = myTabView.getTab(0);
tab0.children[0].text = "Some Text"; // I get Undefined Error
I have tried to access the component using a function inside the Tab:
import QtQuick 2.0
import QtQuick.Controls 2.14 as QQC2
import QtQuick.Layouts 1.14
import QtQuick.Controls 1.4 as QQC1
QQC2.Item {
QQC1.TabView {
QQC1.Tab {
title: "tab1"
function printValue () {
console.log("myTextFld.txt: "+myTextFld.txt); // <-- Getting Error myTextFld undefined.
}
Rectangle {
id: tabHolderRext
color: "blue"
GridLayout {
id: myGrid
model: 7
Repeater {
id: herderRepeater
model: header
delegate: Rectangle {
TextField {
// I want to Access This TextField also
}
}
}
Rectangle {
id: row0Rect
Layout.row: 0
Layout.column: index
TextFiled {
id: myTextFld
text: modelData
}
}
// Rest of the rows
}
}
}
}
}
Item id can be used to access the values from TextField if you have all items in same qml file. If you have different qml files then make use of alias types link to access the values.
Repeater case: The Textfield has to update the underlying modelview --> model first then we can make use of the model's data.
Here is a sample code. I have stacked all item's in the same qml file so that access by id works here.
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window {
visible: true
width: 640
height: 480
Item {
anchors.fill: parent
anchors.margins: 10
TabView {
anchors.fill: parent
Tab {
title: "TextField"
Item {
anchors.fill: parent
Grid {
spacing: 20
anchors.fill: parent
anchors.margins: 10
Rectangle {
height: 40
width: 150
TextField {
id: inputId
anchors.fill: parent
placeholderText: "enter text"
}
}
Button {
height: 40
width: 150
text: "show txt"
onClicked: labelId.text = inputId.text
}
Rectangle {
height: 40
width: 150
Label {
id: labelId
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
}
}
Tab {
title: "Repeater"
Item {
anchors.fill: parent
Grid {
spacing: 20
anchors.fill: parent
anchors.margins: 10
columns: 3
ListModel {
id: fruitModel
ListElement { name: "Apple" }
ListElement { name: "Orange" }
ListElement { name: "Banana" }
}
Repeater {
width: parent.width
height: parent.height / 2
model: fruitModel
delegate: Rectangle {
height: 40
width: 150
TextField {
anchors.fill: parent
text: name
onTextChanged: fruitModel.setProperty(index, "name", text) // update model data
}
}
}
Repeater {
width: parent.width
height: parent.height / 2
model: fruitModel
delegate: Rectangle {
height: 40
width: 150
Label {
text: name
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
}
}
}
}
}
}
I'm trying to create accordion qml control like this.
First I thought that I can use combobox and customize it but now I think it is impossible.
Is there any standerd control that I can use? If not can you help me with controls structure?
Just playing with QML
PanelItem.qml
import QtQuick 2.7
import QtQuick.Layouts 1.2
Item {
default property var contentItem: null
property string title: "panel"
id: root
Layout.fillWidth: true
height: 30
Layout.fillHeight: current
property bool current: false
ColumnLayout {
anchors.fill: parent
spacing: 0
Rectangle {
id: bar
Layout.fillWidth: true
height: 30
color: root.current ? "#81BEF7" : "#CEECF5"
Text {
anchors.fill: parent
anchors.margins: 10
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
text: root.title
}
Text {
anchors{
right: parent.right
top: parent.top
bottom: parent.bottom
margins: 10
}
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: "^"
rotation: root.current ? "180" : 0
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
root.current = !root.current;
if(root.parent.currentItem !== null)
root.parent.currentItem.current = false;
root.parent.currentItem = root;
}
}
}
Rectangle {
id: container
Layout.fillWidth: true
anchors.top: bar.bottom
implicitHeight: root.height - bar.height
clip: true
Behavior on implicitHeight {
PropertyAnimation { duration: 100 }
}
}
Component.onCompleted: {
if(root.contentItem !== null)
root.contentItem.parent = container;
}
}
}
usage:
import QtQuick 2.7
import QtQuick.Layouts 1.2
import QtQuick.Window 2.0
Window {
visible: true
width: 400
height: 400
ColumnLayout {
anchors.fill: parent
spacing: 1
property var currentItem: null
PanelItem {
title: "Panel 1"
Rectangle {
color: "orange"
anchors.fill: parent
}
}
PanelItem {
title: "Panel 2"
Rectangle {
color: "lightgreen"
anchors.fill: parent
}
}
PanelItem {
title: "Panel 3"
Rectangle {
color: "lightblue"
anchors.fill: parent
}
}
PanelItem {
title: "Panel 4"
Rectangle {
color: "yellow"
anchors.fill: parent
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
}
}
What about using this open source component which I did here
Accordion component and used here Accordion component example.
You only need to initialize:
Components.Accordion {
id: acordion
anchors.fill: parent
anchors.margins: 10
}
And create the data dynamically like this:
propertyAcordion.model = [
{
'menuTitle': value,
'children': [
{
'menuTitle': value,
'children': [
...
Updating the MouseArea click part as below with some added condition. Thanks to folibis for this qml accordian menu.
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
root.current = !root.current;
if(root.parent.currentItem !== null) {
if(root.parent.currentItem !== root)
root.parent.currentItem.current = false;
}
root.parent.currentItem = root;
}
}
I am working on some QML + c++ project and, I have a little problem with QML layouts:
I have two custom components :
First one: is a side-bar "SideTabBar.qml" (the purple rectangle in the image below).
Second one: is the element in the side-bar "SideBarElement.qml".
This image describes what I am talking about:
What I want is: highlight each side bar element on click.
To do so I am trying to iterate over the columnLayout children and lowlight them excepting the clicked one. But, I have not managed to make it works.
SideTabBar.qml:
Item {
id: sideTabBar
width: 70
height: parent.height
property string activeElement: ""
ColumnLayout{
id:sidebarLayout
anchors.fill: parent
spacing:2
SideBarElement{elementId:"a1";image:"../assets/product.svg"}
SideBarElement{elementId:"a2";image:"../assets/product.svg"}
Item {Layout.fillHeight: true}
}
}
SideBarElement.qml:
Item {
property alias image: sideBarElementicon.source
property string elementId: ""
id: sideBarElement
width:parent.width
Layout.preferredHeight: 70
Layout.alignment: Qt.AlignTop
Rectangle{
anchors.fill: parent
color:Qt.rgba(0,0,0,0)
}
Image {
id: sideBarElementicon
source: "genericIcon.png"
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
width: 50
height: 50
}
MouseArea{
anchors.fill: parent
onClicked:{ sideTabBar.activeElement = elementId
// compiler does not even enter this loop.
// for(var child in Layout.children){
// console.log("this is a child")
// }
}
}
}
In this case it is better to work with a Repeater since it has an associated index and use a model to set the properties:
SideBarElement.qml
import QtQuick 2.0
Item {
property alias icon: sideBarElementicon.source
property bool highlight: false
width: parent.width
Rectangle{
anchors.fill: parent
color: highlight ? Qt.rgba(1,1,0,1) : Qt.rgba(0,0,0,0)
}
Image {
id: sideBarElementicon
source: "genericIcon.png"
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
width: 50
height: 50
}
}
SideTabBar.qml
import QtQuick 2.0
import QtQuick.Layouts 1.11
Item {
id: sideTabBar
width: 70
height: parent.height
property int currentIndex: -1
ListModel{
id: elements
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
}
Rectangle{
anchors.fill: parent
color: "purple"
}
ColumnLayout{
id:sidebarLayout
anchors.fill: parent
spacing:2
Repeater{
model: elements
SideBarElement{
id: element
highlight: ix == currentIndex
icon: image
property int ix: index
Layout.preferredHeight: 70
Layout.alignment: Qt.AlignTop
MouseArea{
anchors.fill: parent
onClicked: currentIndex = ix
}
}
}
Item {Layout.fillHeight: true}
}
}
I want to make a ToolTip for a delegate Component in a TableView. It works fine, if I use an ItemDelegate, however, I cannot use an ItemDelegate as it destroys the selection mode of TableView. If I try to define the ToolTip in my delegate component I get the error
qrc:/FileSystem.qml:34 Invalid component body specification
How can I use a ToolTip for a Component?
Here is my code:
TreeView {
id: view
anchors.fill: parent
sortIndicatorVisible: true
model: fileSystemModel
rootIndex: rootPathIndex
selection: sel
selectionMode: 2
Component {
id: mycomp
Row{
id: myrow
CheckBox{
id: cbox
anchors.baseline: ctext.baseline
}
Text{
id: ctext
text: styleData.value
color: styleData.textColor
width: namecolumn.width-cbox.width-myrow.x
elide: Text.ElideRight
}
}
NC.ToolTip {
parent: mycomp
visible: hovered
delay: 1000
text: qsTr(styleData.value)
}
}
TableViewColumn {
id: namecolumn
title: "Name"
role: "fileName"
resizable: true
width: parent.width-sizeWidth-dateWidth-scrollBarWidth
delegate: mycomp
}
A component must consist of exactly one "child". So you could try to wrap the contents of the component into an Item, something like this:
Component {
Item {
width: parent.width
height: myrow.height
Row{
id: myrow
CheckBox{
id: cbox
anchors.baseline: ctext.baseline
}
Text{
id: ctext
text: styleData.value
color: styleData.textColor
width: namecolumn.width-cbox.width-myrow.x
elide: Text.ElideRight
}
}
MouseArea {
id: mouseArea
anchors.fill: true
hoverEnabled: true
}
NC.ToolTip {
visible: mouseArea.containsMouse
delay: 1000
text: qsTr(styleData.value)
}
}
}
My question is kind of a two part conditional question. I have a desktop application I'm writing in C++/Qt. In the app I have a couple lists that I want to decorate and add list items with icons and rich text.
I first attempted to do this with the QWidget world but the more I looked into it, the more I thought QML might be a better option. But now I'm wondering about that as well since it seems that QML Is more geared toward touch screen devices. Not to mention that my progress with QML has been frusating. Give them QML below, I cannot figure out how to: (1) get an item to highlight when I click it and (2) add a scroll bar:
import QtQuick 1.0
Item
{
width: 300
height: 200
ListModel
{
id: myModel2
ListElement { text: "List Item 1" }
ListElement { text: "List Item 2" }
ListElement { text: "List Item 3" }
ListElement { text: "List Item 4" }
ListElement { text: "List Item 5" }
ListElement { text: "List Item 6" }
}
Component
{
id: beerDelegate
Rectangle
{
id: beerDelegateRectangle
height: beerDelegateText.height * 1.5
width: parent.width
Text
{
id: beerDelegateText
text: "<b>" + modelData + "</b> <i>(" + modelData + ")</i>"
}
MouseArea
{
anchors.fill: parent
onClicked:
{
console.log("clicked: " + modelData + " at index: " + index);
beerList.currentIndex = index;
}
}
}
}
ListView
{
id: beerList
anchors.fill: parent
model: myModel2
delegate: beerDelegate
highlightFollowsCurrentItem: true
highlight: Rectangle
{
width: parent.width
color: "red"
}
focus: true
}
}
How can I accomplish what I'm looking for given this QML? Or is using QML in a QWidget desktop app just a bad idea all around?
For the first question (highlight):
Your list actually draws the highlight, however, your item delegate overpaints this with a white rectangle! Just replace the rectangle with an item and it works:
Component
{
id: beerDelegate
Item
{
...
}
}
For the second question (scroll bars):
As far as I know, QML doesn't provide scroll bars out of the box. There is however the Qt Desktop Components project (git repository) which gives you access to most of the widgets in the QML world. Among them, there is a ScrollArea.
It is no longer necessary to implement the Scrollbars yourself. There is the ScrollView-Item since Qt 5.1. Simply surround a Flickable-Item (e.g. the ListView-Item you use, is also "Flickable") with the ScrollView-Item and you'll be fine:
ScrollView {
ListView {
id: beerList
anchors.fill: parent
model: myModel2
delegate: beerDelegate
highlightFollowsCurrentItem: true
highlight: Rectangle
{
width: parent.width
color: "red"
}
focus: true
}
}
For the second question. i.e Scroll-bar on ListView:
I have created code for scroll bar on ListView. It also can work on the GridView
ScrollBar.qml
import Qt 4.7
Item {
property variant target
width: 8
anchors.top: target.top
anchors.bottom: target.bottom
anchors.margins: 1
anchors.rightMargin: 2
anchors.bottomMargin: 2
anchors.right: target.right
visible: (track.height == slider.height) ? false : true
Image {
id: scrollPath
width: 2
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
source: "qrc:/resources/buttons/slider2.png"
}
Item {
anchors.fill: parent
Timer {
property int scrollAmount
id: timer
repeat: true
interval: 20
onTriggered: {
target.contentY = Math.max(0, Math.min(target.contentY + scrollAmount,
target.contentHeight - target.height));
}
}
Item {
id: track
anchors.top: parent.top
anchors.topMargin: 1
anchors.bottom: parent.bottom
width: parent.width
MouseArea {
anchors.fill: parent
onPressed: {
timer.scrollAmount = target.height * (mouseY < slider.y ? -1 : 1)
timer.running = true;
}
onReleased: {
timer.running = false;
}
}
Image {
id:slider
anchors.horizontalCenter: parent.horizontalCenter
source: "qrc:/resources/buttons/slider.png"
width: parent.width
height: Math.min(target.height / target.contentHeight * track.height, track.height) < 20 ? 20 : Math.min(target.height / target.contentHeight * track.height, track.height)
y: target.visibleArea.yPosition * track.height
MouseArea {
anchors.fill: parent
drag.target: parent
drag.axis: Drag.YAxis
drag.minimumY: 0
drag.maximumY: track.height - height
onPositionChanged: {
if (pressedButtons == Qt.LeftButton) {
target.contentY = slider.y * target.contentHeight / track.height;
}
}
}
}
}
}
}
And I used scroll bar item with ListView in MyListView.qml as:
MyListView.qml
ListView {
id: list
clip: true
anchors.margins: 5
anchors.fill: parent
model: 10
delegate: trackRowDelegate
interactive: contentHeight > height
}
ScrollBar {
id: verticalScrollBar
target: list
clip: true
}
This ScrollBar item can be used with GridView as
GridView {
id: grid
clip: true
anchors.margins: 5
anchors.fill: parent
cellWidth:100
cellHeight: 100
model: items
interactive: contentHeight > height
snapMode: GridView.SnapToRow
delegate: myDelegate
}
ScrollBar {
id: verticalScrollBar
target: grid
clip: true
visible: grid.interactive
}