I can create "+" (plus) button under all listview items.
This button will add a new item.
I can place it under all exsisting items. But ideály as a part as list.Because of scrolling, scrollbars and other standard listview functions. If listview will be not fill all available page size, scrolls will be ended in the middle of the screan etc...
I tested counting onpaint signal or something like this, but have no success. Because signal for one row goint more than one times, counting is mismatched and button is one time in seccond row, one time below third, sometimes is missing etc...
Example image:
Source code:
import QtQuick 2.10
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0
Page {
title: qsTr("Page 1")
anchors.fill: parent
focus: true
property int myIndex: 0
function setVisibility()
{
if(myModel.rowCount()*3 === myIndex)
{
myIndex = 0
return true
}
else
{
myIndex = myIndex + 1
return false
}
}
/*
*
*
* ListView Component
*
*
*/
ListView
{
id: listView1
model: myModel
currentIndex: 0
//property int actualHeight
anchors.fill: parent
clip: true
//spacing: 40
highlightMoveDuration: 1
highlightMoveVelocity: 1
highlightResizeDuration: 0.0
highlight: Rectangle
{
color: "#2e6377"
opacity: 0.3
}
delegate: hDelegate
}
/*
*
*
* ListViewItem Component
*
*
*/
Component
{
id: hDelegate
Item
{
width: parent.width
height: taskInfo.implicitHeight
property variant mainData: model
MouseArea
{
anchors.fill: parent
onClicked:
{
listView1.currentIndex = index
gIdd = listView1.currentItem.mainData.task_idd
gSubject = listView1.currentItem.mainData.task_subject
gBody = listView1.currentItem.mainData.task_body
listView1.currentIndex = index
}
onDoubleClicked:
{
listView1.currentIndex = index
stackView.push("page3.qml")
}
onPressAndHold:
{
listView1.currentIndex = index
stackView.push("page3.qml")
}
hoverEnabled: true
}
Row
{
id: taskInfo
spacing: 5
Rectangle
{
id: dificultStatus
height: taskColumn.height
width: taskColumn.height
color: "transparent"
Rectangle
{
id: rect22
color: "green"
width: parent.width - 20
height: parent.height - 20
radius: 15
border.color: "lightsteelblue"
border.width: 1
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
Column
{
id: taskColumn
width: listView1.width - editButton.width - dificultStatus.width - 10
Row
{
Text
{
text: task_subject
color: "lightsteelblue"
horizontalAlignment: Text.AlignRight
wrapMode: Text.WordWrap
font {family: localFont.name; pointSize: 14; letterSpacing: 1; wordSpacing: 1}
}
Text
{
text: task_subject
color: "lightsteelblue"
wrapMode: Text.WordWrap
font {family: localFont.name; pointSize: 14; letterSpacing: 1; wordSpacing: 1}
}
}
Text
{
id: text1
height: 50
width: parent.width
clip: true
text: task_body
color: "lightsteelblue"
wrapMode: Text.WordWrap
font {family: localFont.name; pointSize: 14; letterSpacing: 1; wordSpacing: 1}
}
}
Button
{
id: editButton
height: taskColumn.height
width: taskColumn.height
background:
Rectangle
{
anchors.fill: parent
color: "transparent"
Rectangle
{
color: "transparent"
width: parent.width - 20
height: parent.height - 20
radius: 15
border.color: "lightsteelblue"
border.width: 1
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
Text {
anchors.fill: parent
text: qsTr("...")
color: "lightsteelblue"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: 24
anchors.centerIn: parent
}
onClicked:
{
listView1.currentIndex = index
gIdd = listView1.currentItem.mainData.task_idd
gSubject = listView1.currentItem.mainData.task_subject
gBody = listView1.currentItem.mainData.task_body
listView1.currentIndex = index
stackView.push("page3.qml")
}
}
/*
*
*
* AddButton Component
*
*
*/
Button
{
height: taskColumn.height
width: taskColumn.height
x: 0
y: 80
visible: setVisibility()
//visible: (myModel.rowCount() === ++myIndex) ? true : false
background:
Rectangle
{
anchors.fill: parent
color: "transparent"
Rectangle
{
color: "transparent"
width: parent.width - 20
height: parent.height - 20
radius: 15
border.color: "lightsteelblue"
border.width: 1
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
Text {
anchors.fill: parent
text: qsTr("+")
color: "lightsteelblue"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: 24
anchors.centerIn: parent
}
onClicked:
{
listView1.currentIndex = index
gIdd = listView1.currentItem.mainData.task_idd
gSubject = listView1.currentItem.mainData.task_subject
gBody = listView1.currentItem.mainData.task_body
listView1.currentIndex = index
stackView.push("page2.qml")
}
}
}
}
}
}
You can just use ListView's footer property. The default footerPositioning is what you want.
Related
I'm using the example from QML website on how to customize ComboBox as seen below:
#Combo.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
ComboBox {
id: control
model: ["First", "Second", "Third"]
delegate: ItemDelegate {
width: control.width
contentItem: Text {
text: modelData
color: "#21be2b"
font: control.font
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
highlighted: control.highlightedIndex === index
}
indicator: Canvas {
id: canvas
x: control.width - width - control.rightPadding
y: control.topPadding + (control.availableHeight - height) / 2
width: 12
height: 8
contextType: "2d"
Connections {
target: control
function onPressedChanged() { canvas.requestPaint(); }
}
onPaint: {
context.reset();
context.moveTo(0, 0);
context.lineTo(width, 0);
context.lineTo(width / 2, height);
context.closePath();
context.fillStyle = control.pressed ? "#17a81a" : "#21be2b";
context.fill();
}
}
contentItem: Text {
leftPadding: 0
rightPadding: control.indicator.width + control.spacing
text: control.displayText
font: control.font
color: control.pressed ? "#17a81a" : "#21be2b"
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
implicitWidth: 120
implicitHeight: 40
border.color: control.pressed ? "#17a81a" : "#21be2b"
border.width: control.visualFocus ? 2 : 1
radius: 2
}
popup: Popup {
y: control.height - 1
width: control.width
implicitHeight: contentItem.implicitHeight
padding: 1
contentItem: ListView {
clip: true
implicitHeight: contentHeight
model: control.popup.visible ? control.delegateModel : null
currentIndex: control.highlightedIndex
// ADDED SECTION TO CHANGE BACKGROUND OF LISTVIEW
delegate: Rectangle {
color: "#080808"
Text {
anchors.fill: parent
text: modelData
}
}
///////////////////////////////////////////////////
ScrollIndicator.vertical: ScrollIndicator { }
}
background: Rectangle {
color: "#080808"
radius: 2
}
}
}
#main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Combo {
width: 200
height: 40
anchors.centerIn: parent
}
}
I added some new code to Combo.qml as seen above to turn the background of the ListView items to a darker color to match the background color of the Popup itself, but nothing is changing. The ListView background color for the items is always white. I'd appreciate some help on figuring this out. Thanks
There are two issues going on. First, the delegate: on the ComboBox apparently takes precedence over the delegate: on the ListView. Second, the ItemDelegate has some pretty specific highlighting behavior so you need to override it's background and the coloring behavior of it like this:
import QtQuick 2.12
import QtQuick.Controls 2.12
ComboBox {
id: control
model: ["First", "Second", "Third"]
delegate: ItemDelegate {
id: itemDelegate
width: control.width
background: Rectangle {
visible: itemDelegate.down || itemDelegate.highlighted || itemDelegate.visualFocus
color: itemDelegate.highlighted ? "#808080" : "#080808"
implicitWidth: 100
implicitHeight: 40
}
contentItem: Text {
text: modelData
color: "#21be2b"
font: control.font
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
highlighted: control.highlightedIndex === index
}
indicator: Canvas {
id: canvas
x: control.width - width - control.rightPadding
y: control.topPadding + (control.availableHeight - height) / 2
width: 12
height: 8
contextType: "2d"
Connections {
target: control
function onPressedChanged() { canvas.requestPaint(); }
}
onPaint: {
context.reset();
context.moveTo(0, 0);
context.lineTo(width, 0);
context.lineTo(width / 2, height);
context.closePath();
context.fillStyle = control.pressed ? "#17a81a" : "#21be2b";
context.fill();
}
}
contentItem: Text {
leftPadding: 0
rightPadding: control.indicator.width + control.spacing
text: control.displayText
font: control.font
color: control.pressed ? "#17a81a" : "#21be2b"
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
implicitWidth: 120
implicitHeight: 40
border.color: control.pressed ? "#17a81a" : "#21be2b"
border.width: control.visualFocus ? 2 : 1
radius: 2
}
popup: Popup {
y: control.height - 1
width: control.width
implicitHeight: contentItem.implicitHeight
padding: 1
contentItem: ListView {
clip: true
implicitHeight: contentHeight
model: control.popup.visible ? control.delegateModel : null
currentIndex: control.highlightedIndex
// ADDED SECTION TO CHANGE BACKGROUND OF LISTVIEW
// delegate: Rectangle {
// width: parent.width
// height: 40
// color: "#080808"
// Text {
// anchors.fill: parent
// text: modelData
// }
// }
///////////////////////////////////////////////////
ScrollIndicator.vertical: ScrollIndicator { }
}
background: Rectangle {
color: "#080808"
radius: 2
}
}
}
I have the following SpinBox model which I am trying to recreate using the new QtQuick.Control 2, because this one it's using version 1. And I've encountered some problems which I am not sure how to solve.
On the validation side, I should not be able to write anything on the suffix side, just on the number part. Also I should not be allowed to remote the suffix from there while editing
My width should be fixed and I should not be allowed to write more than that.
My Code:
import QtQuick 2.6
import QtQuick.Controls 2
import QtQuick.Controls.Styles 1.4
import QtGraphicalEffects 1.0
SpinBox {
id: root
property color borderColor: "red"
property string multipleValuesTooltip: ""
property color backgroundColor: "yellow"
property bool showTooltip: true
font.pointSize: 10
property int maximumValue: 50
property int minimumValue: 0
property string suffix: ""
property int decimals: 0
to: maximumValue
from: minimumValue
editable: true
rightPadding: {
console.log(root.contentItem.height)
return Math.max(40, Math.round(root.contentItem.height))
}
textFromValue: function(value, locale) {
return qsTr("%1"+suffix).arg(value);
}
contentItem: TextInput {
z: 5
text: root.textFromValue(root.value, root.locale)
font: root.font
color: "white"
selectionColor: "#21be2b"
selectedTextColor: "#ffffff"
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
validator: root.validator
inputMethodHints: Qt.ImhFormattedNumbersOnly
}
up.indicator: Rectangle {
height: parent.height / 2
anchors.right: parent.right
anchors.top: parent.top
implicitWidth: 20 // Adjust width here
implicitHeight: {
console.log(root.contentItem.height)
return root.contentItem.height - 10
}
color: root.up.pressed ? "red" : "pink"
Image {
source: "qrc:/resources/arrow-down.png"
height: Math.min(15, sourceSize.height)
width: Math.min(30, sourceSize.width)
anchors.centerIn: parent
rotation: 180
}
}
down.indicator: Rectangle {
height: parent.height / 2
anchors.right: parent.right
anchors.bottom: parent.bottom
implicitHeight: root.contentItem.height - 10
implicitWidth: {
console.log("W: ",root.width)
return 20
}
color: root.down.pressed ? "red" : "pink"
Image {
source: "qrc:/resources/arrow-down.png"
height: Math.min(15, sourceSize.height)
width: Math.min(30, sourceSize.width)
anchors.centerIn: parent
}
}
background: Item {
implicitHeight: root.height === 0 ? Math.max(30, Math.round(root.contentItem.height * 1.2)) : root.height
implicitWidth: root.contentItem.width + leftPadding +rightPadding
baselineOffset: root.anchors.baselineOffset
Rectangle {
id: baserect
anchors.fill: parent
color: "purple"
radius: 3
}
Rectangle { // Border only
anchors.fill: parent
border.color: "black"
color: "transparent"
radius: 3
}
Rectangle {
anchors.right: parent.right
anchors.rightMargin: root.rightPadding - 10
anchors.verticalCenter: parent.verticalCenter
color: "black"
height: parent.height - parent.height/5
width: 1
}
}
}
I couldn't find any documentation or any kind of information regarding this wherever I've searched for. If any of you could help me I would be really grateful.
I have a ListView where the items become visible or not based on whether a header was expanded or not. When the visible property is set to false, there is just blank space in that area. How do I remove the black space in the list so that the next visible item comes in view?
Currently I have set the height:model.count * 50 with 50 being height of each item. I tried subtracting 50 every time an item's visible property is set to false but this just reduces the height of the list overall but the blank space remains.
ListView { id: list
focus: true
anchors.top: header.bottom
anchors.left: parent.left
anchors.right: parent.right
width: parent.width
height:model.count*50
model:hall
Component {
id:comp
Item{
width: parent ? parent.width : 0
height: parent ? parent.height: 0
Column{
id:col1
width: parent.width - 16
height: 25
anchors.centerIn: parent
spacing: 3
Text { id: name
width: parent.width
text: name
elide: Text.ElideMiddle
font: "black"
color: "grey"
}
Row{
width: parent.width
Text { id: file1
width: parent.width * 0.6 - 5
text: "hello"
horizontalAlignment: Text.AlignLeft
elide: Text.ElideMiddle
font: systemFont.TableCellFont
}
Text { id: file2
width: parent.width*0.4 - 3
horizontalAlignment: Text.AlignRight
text: mod
font: systemFont.TableCellFont
}
}
}
MouseArea {
anchors.fill: parent
onClicked: {
console.warn("Mouse onClicked")
}
}
}
}
delegate: Item {
width: parent.width;
height: {
if (!cric && expanded)
return 50
else
return 0
}
Loader {
anchors.fill: parent
sourceComponent: comp
height: expanded? 50: 0
readonly property int index:model.index
readonly property string mod: model.mod
visible: !cric && expanded
}
}
Keys.onReturnPressed: {
console.warn("Return pressed")
}
}
The blank space is created because the List item which is hidden by setting visible to false still has its dimensions set. You can update the item height to 0 and the blank space will not be visible. Try this example for reference.
import QtQuick 1.1
Rectangle{
width: 400; height: 400
color: 'lightblue'
ListView{
width: 400; height: count * 30
model: 20
delegate: Rectangle{
id: rectDel
width: 200; height: 30
color: 'lightgreen'
border{
width: 1
color: 'black'
}
Text{
text: index
anchors.centerIn: parent
}
Rectangle{
width: 20; height: 20
radius: 10
color: 'red'
anchors{
verticalCenter: parent.verticalCenter
right: parent.right; rightMargin: 10
}
Text{ text: 'X'; anchors.centerIn: parent; }
MouseArea{
anchors.fill: parent
onClicked: {
rectDel.visible = false
rectDel.height = 0
}
}
}
}
}
}
At first it seemed to work fine.
However, when the number of models exceeded 20, items after 20 were not checked.
How can the listview's checkbox work normally even when the number of models is large?
Rectangle {
id : infoTable
width: parent.width - 20
height: 295
anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
id: header
width: parent.width
height: 31
anchors{
top: parent.top
topMargin: 5
horizontalCenter: parent.horizontalCenter
}
Row {
height: parent.height
anchors.left: parent.left
Item {
width: headerModel.get(0).columnWidth
height: parent.height
Label {
text: headerModel.get(0).name
font.family: Theme.nanumSquareBold.name
font.pixelSize: Theme.regularSize
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}
Item {
width: headerModel.get(1).columnWidth
height: parent.height
ButtonGroup{
id : checkboxGroup
exclusive: false
checkState: headerCheckbox.checkState
}
CheckBox{
id : headerCheckbox
anchors.centerIn: parent
scale: 0.7
checkState: checkboxGroup.checkState
}
}
}
}
Rectangle {
width: parent.width
height: parent.height - 31
anchors{
top: header.bottom
topMargin: 2
horizontalCenter: parent.horizontalCenter
}
ListView {
id: tableView
property int itemHeight: 30
width: parent.width
height: parent.height
headerPositioning: ListView.InlineHeader
boundsMovement: Flickable.StopAtBounds
currentIndex: -1
focus: true
clip: true
model : viewModel.myModel
ListModel {
id: headerModel
ListElement { name: "No"; columnWidth: 30 }
ListElement { name: ""; columnWidth: 35 }
}
delegate: Rectangle {
width: parent.width
height: tableView.itemHeight
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton | Qt.LeftButton
onClicked: {
if (mouse.button == Qt.RightButton){
tableMouseMenu.popup()
}
}
}
Row {
height: parent.height
Item {
width: headerModel.get(0).columnWidth
height: parent.height
Label {
text: index + 1
font.bold: true
font.pixelSize: 12
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}
Item {
width: headerModel.get(1).columnWidth
height: parent.height
Item {
anchors.fill: parent
CheckBox {
id : checkbox
scale: 0.7
anchors.centerIn: parent
ButtonGroup.group: checkboxGroup
checked: model.check
MouseArea {
anchors.fill:parent
propagateComposedEvents : true
onClicked: {
mouse.accepted = false
model.check=!check
}
}
Connections {
target : headerCheckbox
onClicked : {
if (headerCheckbox.checkState == 2 && !model.check) model.check = true
else if (headerCheckbox.checkState == 0 && model.check) model.check = false
else model.check
console.log(model.check)
}
}
}
}
}
}
}
}
}
}
I need to have drop-down that opens upwards on clicking on Menu button in QML.
I have tried to use the listview for the same, but in the implementation we are getting drop-down which opens downwards.
Any suggestions with reference to below snippet.
import QtQuick 1.1
Rectangle {
width: 800
height: 480
Rectangle {
id:comboBox
property variant items: ["Red", "Blue", "Green"]
signal comboClicked;
x: 651
y: 344
width: 141
height: 30;
z: 0
smooth:true;
Rectangle {
id:chosenItem
radius:4;
width:parent.width;
height:comboBox.height;
color: "#454b4d"
smooth:true;
Text {
anchors.top: parent.top;
anchors.margins: 8;
id:chosenItemText
x: 11
y: 5
color: "#ffffff"
text:"Menu";
anchors.topMargin: 5
anchors.left: parent.left
anchors.leftMargin: 12
font.family: "Arial"
font.pointSize: 14;
smooth:true
}
MouseArea {
width: 400
height: 30
anchors.bottomMargin: 0
anchors.fill: parent;
onClicked: {
comboBox.state = comboBox.state==="dropDown"?"":"dropDown"
}
}
}
Rectangle {
id:dropDown
width:comboBox.width;
height:0;
clip:true;
radius:4;
anchors.top: chosenItem.bottom;
anchors.margins: 2;
color: "lightblue"
ListView {
id:listView
height:500;
model: comboBox.items
currentIndex: 0
delegate: Item{
width:comboBox.width;
height: comboBox.height;
Text {
text: modelData
anchors.top: parent.top;
anchors.left: parent.left;
anchors.margins: 5;
}
MouseArea {
anchors.fill: parent;
onClicked: {
comboBox.state = ""
chosenItemText.text = modelData;
listView.currentIndex = index;
}
}
}
}
}
states: State {
name: "dropDown";
PropertyChanges { target: dropDown; height:30*comboBox.items.length }
}
transitions: Transition {
NumberAnimation { target: dropDown; properties: "height"; easing.type: Easing.OutExpo; duration: 1000 }
}
}
}
Try to change the anchors of the dropDown item:
that
anchors.top: chosenItem.bottom;
should become
anchors.bottom: chosenItem.top;