I'm trying to make scrollable list in QML.
Though its running successfully but whenever am varying the size of main window the pattern of the list distorts or the items overlaps on each other.
Any suggestions where is the bug in my code.
Tried to vary the anchors but then also no luck on the issue.
Below is the code snippet
import QtQuick 1.1
Item{
....
Rectangle{
....
Rectangle {
....
color: "white"
anchors.centerIn: main.Center
Rectangle {
...
ListView {
id: list_min
....
snapMode: ListView.SnapToItem
model: 20
delegate: Rectangle{
width: list_min.width
height: list_min.height
color: "transparent"
Text {
anchors.verticalCenter: parent.verticalCenter
text: index+1
font.pixelSize: parent.width/1.5
}
Text {
text: index+2
font.pixelSize: parent.width/1.5
anchors.top: parent.top
anchors.topMargin: 150
}
Text {
text: index
font.pixelSize: parent.width/1.5
anchors.bottom: parent.bottom
anchors.bottomMargin: 150
}
}
onMovementEnded: list_min.currentIndex = list_min.visibleArea.yPosition * list_min.count
Component.onCompleted: list_min.visibleArea
}
Rectangle {
....
gradient: Gradient {
GradientStop { position: 0.0; color: "black" }
....
GradientStop { position: 1.0; color: "black" }
}
}
}
}
I would recommend using the Column tag to place the text elements in the delegate.
Also for overlay_min, you need to either set the height & width OR the anchors.fill, not both.
I have modified the source code as below:
import QtQuick 1.1
Item{
width: 300
height: 240
Rectangle{
id:main
width: parent.width
height: parent.height
Rectangle {
id :frame_min
width: 120
height: main.height
color: "white"
anchors.centerIn: main.Center
Rectangle {
id: mSpinner
anchors.centerIn: parent
width: frame_min.width - 10
height: frame_min.height
color: "white"
border.color: "black"
border.width: 5
ListView {
id: list_min
width: mSpinner.width
height: mSpinner.height
anchors.topMargin: 0
anchors.top: parent.top
clip: true
snapMode: ListView.SnapToItem
model: 20
delegate: Rectangle{
width: list_min.width
height: list_min.height
color: "transparent"
Column{
anchors.verticalCenter: parent.verticalCenter
Text {
//anchors.verticalCenter: parent.verticalCenter
text: index+1
font.pixelSize: list_min.width/1.5
}
Text {
text: index+2
font.pixelSize: list_min.width/1.5
//anchors.top: parent.top
//anchors.topMargin: 150
}
Text {
text: index
font.pixelSize: list_min.width/1.5
//anchors.bottom: parent.bottom
//anchors.bottomMargin: 150
}
}
}
onMovementEnded: list_min.currentIndex = list_min.visibleArea.yPosition * list_min.count
Component.onCompleted: list_min.visibleArea
}
Rectangle {
id: overlay_min
width: frame_min.width
height: frame_min.height
//anchors.fill: frame_min
gradient: Gradient {
GradientStop { position: 0.0; color: "black" }
GradientStop { position: 0.34; color: "transparent" }
GradientStop { position: 0.35; color: "white" }
GradientStop { position: 0.66; color: "transparent" }
GradientStop { position: 1.0; color: "black" }
}
}
}
}
}
}
Related
I am trying to create a slider that I can move up and down with my mouse. However, I want to use my own image as the background. I am currently trying to implement this with a OpacityMask. Basically, I am trying to make the opacity 0 from where the handle is to the right end of the slider.
I would ordinarily just move a rectangle that is same color as the background over it. However, I want whatever element is under the slider to be displayed when the slider is pulled back.
How can I create this behavior?
import QtQuick 2.7
import QtQuick.Templates 2.0 as T
import QtGraphicalEffects 1.12
import "."
T.Slider {
id: control
implicitWidth: 200
implicitHeight: 26
handle: Rectangle {
x: control.visualPosition * (control.width - width)
y: (control.height - height) / 2
width: 20
height: 15
radius: 5
color: control.pressed ? "#f0f0f0" : "#f6f6f6"
border.color: "gray"
}
background: OpacityMask {
anchors.fill: sliderImage
source: sliderImage
maskSource: mask
}
Image{
id: sliderImage
source: "./Jarvis2/images/volume_barH.png"
height: 20
width: parent.width
visible: false
}
Item{
id: mask
anchors.fill: sliderImage
Rectangle{
id: outer
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
width: control.visualPosition*parent.width
color: "gray"
opacity: 1
visible: false
}
Rectangle {
id: inner
color: "transparent"
z: 1
opacity: 1
anchors.left: outer.right
anchors.right: parent.right
anchors.top: outer.top
anchors.bottom: outer.bottom
visible: false
}
}
}
The slider at 100%:
The slider at around 70%:
The slider at around 24%
I think you can omit the OpacityMask and simply use a clipping Item:
Slider {
id: slider
width: 100
height: 300
orientation: Qt.Vertical
background: Item {
id: background
Item {
clip: true
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: (1 - slider.visualPosition) * slider.height
Rectangle { //Your image goes here
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: background.height
gradient: Gradient {
GradientStop { position: 0; color: "blue" }
GradientStop { position: 1; color: "red" }
}
}
}
}
}
You might have to fiddle a bit with the height of the clipping Item since there is some padding involved.
If you nevertheless want to use OpacityMask (because you want a different shape), you should put them together in the background:
Slider {
id: slider
width: 100
height: 300
orientation: Qt.Vertical
background: Item {
id: background
Rectangle { //Your image goes here
id: image
anchors.fill: parent
visible: false
gradient: Gradient {
GradientStop { position: 0; color: "blue" }
GradientStop { position: 1; color: "red" }
}
}
OpacityMask {
anchors.fill: parent
source: image
maskSource: mask
}
Item {
id: mask
visible: false
anchors.fill: parent
Rectangle {
radius: 10
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: parent.height * slider.position
color: "white"
}
}
}
}
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.
I have two items that are stacked. Both items have a semi-transparent background. The circle now shows the the rounded rect below.
Is there any way I can hide the part of the long rounded rect that overlaps with the circle? Maybe changing the parent, that the background of the circle is pulled from the ancestor higher up, and therefore ignoring the rect immediately below it?
Here is the code:
Item
{
id: choice1
width: 300
height: 100
Rectangle
{
id: choiceLabel1
width: 0
height: parent.height / 1.5
radius: parent.height * 0.5
color: "#88808080"
anchors
{
verticalCenter: choice1.verticalCenter
left: choice1.left
leftMargin: choiceIcon1.width / 2
}
border
{
width: 2
color: "red"
}
}
Rectangle
{
id: choiceIcon1
width: choice1.height
height: choice1.height
radius: width * 0.5
color: "#88808080"
anchors
{
verticalCenter: choice1.verticalCenter
left: choice1.left
}
border
{
width: 2
color: "red"
}
}
}
A solution, albeit a bit hacky would be to implement your own QML MultiRectangle component, which allow to set an opacity and draw a border around a bunch of QML Rectangle
MultiRectangle.qml
import QtQuick 2.0
Item
{
id: root
layer.enabled: true
property int borderWidth: 2
property color borderColor
Component
{
id: rectangle
Rectangle{}
}
Component.onCompleted:{
var temp = children.length
for(var i=0; i<temp; i++)
rectangle.createObject(this,
{
"z":-100,
"anchors.centerIn": children[i],
"color": borderColor,
"width": children[i].width+borderWidth*2,
"height": children[i].height+borderWidth*2,
"radius": Math.max((children[i].height+borderWidth*2)
/children[i].height*children[i].radius,
(children[i].height+borderWidth*2)
/children[i].height*children[i].radius)
})
}
}
This will dynamically create a pseudo border behind the rectangles added to a MultiRectangle item.
Example
import QtQuick 2.5
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0
Window {
id: root
visible: true
height: 200
width: 400
RadialGradient {
anchors.fill: parent
gradient: Gradient {
GradientStop { position: 0.0; color: "white"}
GradientStop { position: 0.3; color: "#444"}
GradientStop { position: 1; color: "white"}
}
}
MultiRectangle {
anchors.centerIn: parent
width: 300
height: 100
borderWidth: 2
borderColor: "red"
opacity: 0.5
Rectangle {
color: "cyan"
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: parent.borderWidth
height: parent.height - 2 * parent.borderWidth
width: height
radius: height / 2
}
Rectangle {
color: "cyan"
anchors.horizontalCenter: parent.horizontalCenter
anchors.margins: parent.borderWidth
anchors.top: parent.top
height: 10
width: height
radius: height / 2
}
Rectangle {
color: "cyan"
anchors.horizontalCenter: parent.horizontalCenter
anchors.horizontalCenterOffset: 30
anchors.margins: parent.borderWidth
anchors.top: parent.top
height: 30
width: height
radius: height / 2
}
Rectangle {
color: "cyan"
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 50
height: parent.height * 0.6
anchors.right: parent.right
anchors.margins: parent.borderWidth
radius: height / 2
}
}
}
Result
Note that since layer.enabled is set to true, clip is also set to true. Therefore, the border of child items too close to the MultiRectangle bounds will be clipped.
I want to draw a few lines in qml and to relatively place them (and used Rectangle with small width for it).
Line 2 is rotated 45 degrees.
Line 3 is anchored to Line 1 and Line 2.
The issue is when I anchor a Line 3 to Line 2, it takes points before rotation. Is there a way to resolve this?
Rectangle {
id: idLine1
height: 2
color: "white"
width: idFluidStatus.width/3
anchors.left: idRect.right
anchors.verticalCenter: idRect.verticalCenter
}
Rectangle {
id: idLine2
height: 2
color: "white"
transformOrigin: Item.BottomLeft
rotation: 45
width: idFluidStatus.width/3
anchors.left: idRect.horizontalCenter
anchors.top: idLine1.bottom
}
Rectangle {
id: idLine3
height: 2
color: "red"
anchors.left: idLine2.right
anchors.right: idLine1.right
anchors.bottom: idLine2.bottom
}
Expected:
Obtained:
Adding running example code:
import QtQuick 2.0
Rectangle {
id: idFluidStatus
width: 500; height: 400
color: "darkgray"
Rectangle {
id: idLine1
height: 2
color: "white"
width: idFluidStatus.width/3
anchors.left: idRect.right
anchors.verticalCenter: idRect.verticalCenter
}
Rectangle {
id: idLine2
height: 2
color: "white"
transformOrigin: Item.BottomLeft
rotation: 45
width: idFluidStatus.width/3
anchors.left: idRect.horizontalCenter
anchors.top: idLine1.bottom
Component.onCompleted: {
console.log(x, y, width, height)
}
}
Rectangle {
width: 50
height: 50
color: "green"
x: idLine2.x+idLine2.width
y: idLine2.y
}
Rectangle {
id: idLine3
height: 2
color: "red"
anchors.left: idLine2.right
anchors.right: idLine1.right
anchors.bottom: idLine2.bottom
}
Rectangle {
width: idRect.width + 5
height: width
radius: width/2
color: "white"
anchors.centerIn: idRect
}
Rectangle {
id: idRect
width: (idFluidStatus.width < idFluidStatus.height) ? idFluidStatus.width/6 : idFluidStatus.height/6
height: width
radius: width/2
color: "#155B5E"
opacity: 0.7
anchors {
top: idFluidStatus.top
topMargin: idFluidStatus.height/10
left: idFluidStatus.left
leftMargin: idFluidStatus.width/10
}
}
}
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;