How to use toolseparator inside a repeater in qml? - qt

Toolseparator is not working inside repeater. I need to show the image and text under that one line after each content, so to show the line i have used tool separator but it's not working, it just override all the content by showing only lines. Here is the example
Repeater {
model: 10
Row {
leftPadding: 10
spacing: 10
Rectangle {
height: 100
width: 200
}
Text {
text: "Username"
}
ToolSeparator {
height: 25
width: 335
orientation: Qt.Horizontal
}
}
}

You've done few mistakes, my friend.
If you are going to use Repeater -- typically you should use it inside of some of the positioning components (e.g. Column, Row). So in your case, Repeater should be inside Row. By the way, never neglect to review official Qt documentation: Repeater Detailed Description; Using QML Positioner and Repeater Items. In addition to this there is great learning source QmlBook, and for example its Quick Starter.
If you want to show your components one under another -- you should use Column component, and not Row.
If I understand you correctly you are going to get something like this:
Use this code as a reference:
Column {
spacing: 10
Repeater {
model: 4
Rectangle {
id: background
height: 50
width: 200
color: "bisque"
Text {
id: text
color: "chocolate"
text: "Username " + modelData
anchors.centerIn: parent
}
Rectangle {
id: separator
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
}
height: 5
color: "goldenrod"
}
}
}
}

Related

Why do my nested ListViews only show one element of the outer model?

I'm following the code pattern of my unavailable predecessor - using nested ListView's to implement a TreeView-like interface. I'd prefer not to use a TreeView, purely to keep the same patterns throughout the code, rather than introducing more patterns. But I can't get the basics to work with a very simple piece of code!
I've tried looking for a definitive QML/QtQuick reference book but my searches mostly point to people asking why there isn't one. I find my self fighting against QML rather than working WITH it, a sure sign that I need to hit a book. So Question 2 is what should I read?
import QtQuick 2.11
import QtQuick.Window 2.11
import QtQuick.Controls 1.4
Window {
id: theWindow
visible: true
width: 640
height: 480
ListModel {
id: outerModel
ListElement{ display: "One" }
ListElement{ display: "Two" }
ListElement{ display: "Three" }
}
ListModel {
id: innerModel
ListElement{ display: "A" }
ListElement{ display: "B" }
}
Column{
ListView {
model: outerModel
height: 100
width: 200
delegate: Column {
Text {
text: display
}
ListView {
model: innerModel
height: 100
width: 200
delegate: Text {
text: display
}
} // ListView inner
} //delegate Column
} // ListView outer
} // Column
} // Window
I'd expect a result similar to:
One
A
B
Two
A
B
Three
A
B
But I only get
One
A
B
The problem is the fixed height of 100px on both of your ListViews.
Remove the first wrapping Column and set a dyamic height on the inner ListView based on content:
ListView {
model: outerModel
height: parent.height // <====
width: 200
delegate: Column {
Text {
text: display
}
ListView {
model: innerModel
height: contentHeight // <====
width: 200
delegate: Text {
text: display
}
}
}
}
(or implement an actual TreeView :))

If an item within a Row is not visible how to lay it out?

As per the Doc
If an item within a Row is not visible, or if it has a width or height
of 0, the item will not be laid out and it will not be visible within
the row. Also, since a Row automatically positions its children
horizontally, a child item within a Row should not set its x position
or horizontally anchor itself using the left, right,
anchors.horizontalCenter, fill or centerIn anchors. If you need to
perform these actions, consider positioning the items without the use
of a Row.
I couldn't find the best solution for it. Could anyone help me in this regard? See my below code:
Rectangle{
width: parent.width
height: parent.height
Component{
id:itemDelegate
Item {
id: itemId
width: listView.width; height: listView.height * 0.20
Row{
spacing : listView.height * 0.20
Repeater{
model:5
Column{
Button{
text: index
//opacity: (index % 2) === 0 ? 1.0:0.0
visible: (index % 2) === 0 ? true:false
}
Button{
text: index
//opacity: (index % 3) === 0 ? 1.0:0.0
visible: (index % 3) === 0 ? true:false
}
}
}
}
}
}
ListView{
id:listView
anchors.fill: parent
anchors {
left: parent.left; top: parent.top;
right: parent.right
margins: parent.width * 0.08
}
delegate: itemDelegate
model:aaModel
clip:true
}
}
In the output the first indexed Column will be invisible. Hence it won't be laid out and second indexed Column will occupy that space. But I want blank space there. However I can achieve that using opacity at a cost of blank space in third indexed Column (first blank space followed by a button). But I want such a behavior that lifts buttons up in the column if button is not visible along side if all the buttons in Column are invisible the blank space should appear at the place of Column. So here Columns inside the Row would not help me. What is the best way to do this?
Wrapp the Button in an Item
Column {
Button {
text: 'Blue'
}
Item {
width: greenButton.implicitWidth
height: greenButton.implicitHeight
Button {
id: greenButton
visible: false
text: 'Green'
}
}
Button {
text: 'red'
}
}
To make it easier, create a custom component for it (e.g. MyButton.qml):
import QtQuick 2.0
import QtQuick.Controls 2.0
Item {
id: root
property alias button: myButton
implicitHeight: button.height
implicitWidth: button.width
Button {
id: myButton
}
}
Use it like this:
Column {
MyButton {
button {
text: 'green'
onClicked: button.visible = false // Won't shrink the column
}
}
MyButton {
button {
text: 'red'
visible: false
}
}
MyButton {
button {
text: 'orange'
onClicked: visible = false // Will shrink the column
}
}
}

ListView dynamic anchoring

Let us suppose I have a card made using Rectangle and I want to show buttons on top of it when clicked. I'm calling showMenu() function to do that and for buttons I'm using an ListView with dynamic ListModel. The problem with such is that the button gets added bellow the Rectangle instead of the top of it. The anchor is not updating after appending an item to the model. Here is my code
Item {
width: 120
height: 120
Rectangle {
id: card
width: 50
height: 100
color: "pink"
anchors.bottom: parent.bottom
Item {
id: rec
width: 50
anchors.bottom: parent.top // This anchor is not updating after appending an item to the list.
ListModel {
id: menuListModel
}
Component {
id: delegate
Rectangle {
width: 120
height: 20
color: "blue"
Text {
anchors.fill: parent
anchors.centerIn: parent
text: commandText
}
}
}
ListView {
anchors.fill: parent
model:menuListModel
delegate: delegate
interactive: false
}
}
MouseArea {
anchors.fill: parent
onClicked: menuListModel.append({"commandText" : "Normal Summon"});
}
}
}
This is more or less a duplicate of this question. The Item needs a height. As mentioned in the answer to that question, you can add debug statements to the code when things like this happen. In this situation, you can also add a Rectangle as a child of the Item and make sure that it's visible:
Rectangle {
anchors.fill: parent
color: "transparent"
border.color: "darkorange"
}
If it's not visible, you know that the problem lies with that (parent) item.

How do I put an image on items of ListView and change it dynamically?

I'm trying to make a color picker in QML. The color details are stored in a ListModel and I've tried to create a horizontal row of colors to choose from.
Something like this:
The problem is, I'm unable to add a button image over the selected cell. I want to highlight the cell the user has selected by placing an image at the center of that cell.
The following is the code snippet I've written
ListView{
id: list
height: 30
width: 500
anchors.bottom: main.bottom
anchors.horizontalCenter: main.horizontalCenter
anchors.bottomMargin: 40
orientation: ListView.Horizontal
model: myModel
delegate:
Item {
id: cell
property alias cellColor: rectangle.color
signal clicked(color cellColor)
width: 500/myModel.count; height: 25
Rectangle {
id: rectangle
color: clr
anchors.fill: parent
}
onClicked:{
dynamicRect.color=cellColor
list.currentIndex=index
console.log(list.currentIndex)
}
MouseArea {
anchors.fill: parent
z: 1
onClicked: {
cell.clicked(cell.cellColor)
}
}
}
highlight:
Image {
id: button
height: 20
width: 20
source: "button.png"
anchors.horizontalCenter: list.currentItem.horizontalCenter
}
}
Any help will be highly appreciated.
Thanks!

Share equally the horizontal space in a QML Row

I need to share equally the horizontal space between all "buttons" in my Row.
I use this code with a Repeater.
Component {
id: buttonComponent
Rectangle {
height: buttonRow.height
width: buttonRow.width / buttonsRepeater.count
color: "#FFDDDD"
Text {
anchors.centerIn: parent
text: model.text
}
}
}
Rectangle {
color: "#DDDDDD"
id: buttonBar
height: 30
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
}
Row {
id: buttonRow
anchors.fill: parent
Repeater {
id: buttonsRepeater
model: buttonsModel
delegate: buttonComponent
}
}
}
Now, I like to compute the ideal width of the Row such that all my button texts appear correctly.
How can I get this ideal width?
If you don't want to use QtQuick.Layouts as they are not really ready yet, you can use this :
Rectangle {
id: buttonBar;
color: "#DDDDDD";
height: 30;
width: (buttonColumn.width + 20 + buttonRow.spacing) * buttonsRepeater.count;
anchors {
bottom: parent.bottom;
left: parent.left;
}
Column {
id: buttonColumn;
visible: false;
Repeater {
model: buttonsModel;
delegate: Text {
text: model.text;
}
}
}
Row {
id: buttonRow;
anchors.fill: parent;
property real itemWidth : ((width + spacing) / buttonsRepeater.count) - spacing;
Repeater {
id: buttonsRepeater;
model: buttonsModel;
delegate: Component {
id: buttonDelegate;
Rectangle {
height: parent.height;
width: parent.itemWidth;
color: "#FFDDDD";
border.width: 1;
Text {
anchors.centerIn: parent;
text: model.text;
}
}
}
}
}
}
I just used a hidden Column to easily compute max width of Text elements, and added a little padding in the bar width to avoid unspaced text.
The minimum width of a button itself is the implicitWidth property of its Text element.
One solution to your problem might be to add code in the Component.onCompleted handler, i.e. code that is executed after the repeater has created its items, and then sum up these implicitWidth properties of each of the repeater's item (which you can get by using its itemAt(index) function).
These kinds of dynamic layout is a bit cumbersome in QML still, which will get much better in Qt 5.1 with the introduction of Qt Quick Layouts

Resources