How to make Rectangle behaves like a scrollbar in qml - qt

I am trying to make a scroll bar without using ScrollBar Component in QML.
So i have made this component and attach to the ListView. But it doesn't flick the listview items.
I want, this rectangle scrolls the content of ListView or GridView on scrolling.
What I did?
Ist I create a rectangle then make another rectangle as a child of ist one. And applied the dragging technique on Y axis and set the coordinates for y axis.
My Code is given below:
import QtQuick 2.0
Rectangle{
property bool is_parentDrag: false
property bool is_childDrag: false
id:parent_screen
anchors.fill:parent
color:"#ebeaee"
Rectangle{
id:foot
width:parent.width*0.9
height:parent.height*0.133
color:"#ffffff"
border.width:1
anchors.bottom:parent.bottom
anchors.bottomMargin:lv.height*0.005
anchors.horizontalCenter: parent.horizontalCenter
Rectangle{
width:parent.width*0.125
height:parent.height*0.5
radius:20
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: parent.height*0.2
color:"transparent"
Image{
source: "left_direction_icon.png"
anchors.centerIn: parent
sourceSize.width: parent.width*0.4
sourceSize.height: parent.width*0.4
}
MouseArea{
anchors.fill:parent
onClicked: {
stack.pop()
}
}
}
}
Flickable{
id:flick_1
width:parent.width*0.9
height:parent.height*0.7
anchors.centerIn: parent
flickableDirection:Flickable.HorizontalFlick
boundsBehavior: Flickable.StopAtBounds
ListView{
id:lv
clip:true
boundsBehavior: Flickable.StopAtBounds
height:parent.height
width:parent.width*0.9
anchors.left:parent.left
anchors.leftMargin: parent.width*0.11
model:Data{}
delegate: Rectangle{
id:delg
width:lv.width*0.5
height:lv.height*0.170
Text{
text:txt
anchors.centerIn: parent
font.pixelSize: 22
}
Rectangle{
id:right
width:1
height:parent.height
color:"black"
anchors.right:parent.right
}
Rectangle{
id:bottom
width:parent.width
height:1
color:"black"
anchors.bottom:parent.bottom
}
Rectangle{
id:left
width:1
height:parent.height
color:"black"
anchors.left:parent.left
}
}
Rectangle{
id:scrollbar
width:flick_1.width*0.02
height:flick_1.height
visible: lv.contentHeight>lv.height
radius:width/2
color:"lightgrey"
anchors.right: lv.right
anchors.rightMargin: lv.width*0.1
Rectangle {
id:scroll
Drag.active:is_parentDrag?parent_drag_area.drag.active:is_childDrag?drag_area.drag.active:false
Drag.source: scroll
implicitWidth: parent.width
implicitHeight: parent.height*0.7
radius:width/2
opacity:0.85
color: "grey"
MouseArea{
id:drag_area
anchors.fill:parent
drag.target: scroll
drag.axis: Drag.YAxis
drag.minimumY: 0
drag.maximumY: scrollbar.height-scroll.height
onPressed:{
if(is_childDrag)
is_childDrag=false
else
is_childDrag=true
}
}
}
MouseArea{
id:parent_drag_area
anchors.fill:parent
drag.target: scroll
drag.axis: Drag.YAxis
drag.minimumY: 0
drag.maximumY: scrollbar.height-scroll.height
onPressed:{
if(is_parentDrag)
is_parentDrag=false
else
is_parentDrag=true
}
}
}
// Rectangle {
// id: scrollbar
// //height:parent.height*0.04
// width:parent.width
// radius:width/2
// anchors.bottom: parent.bottom
// y: flick_1.visibleArea.yPosition * flick_1.height
// height: flick_1.visibleArea.heightRatio * flick_1.height*0.04
// color: "lightgrey"
// anchors.bottomMargin: parent.height*0.1
// Rectangle {
// id:scroll
// y: flick_1.visibleArea.yPosition * flick_1.height
// implicitWidth: parent.width*0.7
// implicitHeight: parent.height
// radius:width/2
// opacity:0.85
// color: "grey"
// }
// }
}
}
}

You can try this (copied from QML Material Project).
Create a new QML-File called ScrollbarCustom.qml:
Item {
id: root
property Flickable flickableItem
property int orientation: Qt.Vertical
property int thickness: 5
property bool moving: flickableItem.moving
property alias currentY: scrollBar.y
width: thickness
height: thickness
clip: true
smooth: true
visible: orientation === Qt.Vertical ? flickableItem.contentHeight > flickableItem.height
: flickableItem.contentWidth > flickableItem.width
anchors {
top: orientation === Qt.Vertical ? flickableItem.top : undefined
bottom: flickableItem.bottom
left: orientation === Qt.Horizontal ? flickableItem.left : undefined
right: flickableItem.right
margins: 2
}
signal stopAnimation
onStopAnimation: {
hideAnimation.stop();
showAnimation.start();
}
signal startAnimation
onStartAnimation: {
hideAnimation.start();
showAnimation.stop();
}
Component.onCompleted: hideAnimation.start()
onMovingChanged: {
if (moving) {
hideAnimation.stop()
showAnimation.start()
} else {
hideAnimation.start()
showAnimation.stop()
}
}
NumberAnimation {
id: showAnimation
target: scrollBar;
property: "opacity";
to: 0.3;
duration: 200;
easing.type: Easing.InOutQuad
}
SequentialAnimation {
id: hideAnimation
NumberAnimation { duration: 500 }
NumberAnimation {
target: scrollBar;
property: "opacity";
to: 0;
duration: 500;
easing.type: Easing.InOutQuad
}
}
onOrientationChanged: {
if (orientation == Qt.Vertical) {
width = thickness
} else {
height = thickness
}
}
Rectangle {
id: scrollBar
property int length: orientation == Qt.Vertical ? root.height
: root.width;
property int targetLength: orientation == Qt.Vertical ? flickableItem.height
: flickableItem.width;
property int contentStart: orientation == Qt.Vertical ? flickableItem.contentY
: flickableItem.contentX;
property int contentLength: orientation == Qt.Vertical ? flickableItem.contentHeight
: flickableItem.contentWidth;
property int start: Math.max(0, length * contentStart/contentLength);
property int end: Math.min(length,
length * (contentStart + targetLength)/contentLength)
color: Theme.accentColor //"black"//theme.foreground
opacity: 0.2
radius: thickness/2
width: Math.max(orientation == Qt.Horizontal ? end - start : 0, thickness)
height: Math.max(orientation == Qt.Vertical ? end - start : 0, thickness)
x: orientation == Qt.Horizontal ? start : 0
y: orientation == Qt.Vertical ? start : 0
}
}
And use it like this:
Flickable {
id: flickable
clip: true
anchors {
top: parent.top
left: parent.left
right: parent.right
bottom: parent.bottom
}
}
ScrollbarCustom {
flickableItem: flickable
}

A solution is to leverage Qt Quick Templates 2. This Qt module is the base of Qt own controls Qt Quick Controls 2 and contains multiple base UI components that can be fully customized.
In your case, you should look at ScrollBar and how to customize it.
Your code could end up being something like this:
Flickable {
id: flickable
clip: true
// ...
ScrollBar.vertical: ScrollBar {
id: control
size: 0.3
position: 0.2
active: true
orientation: Qt.Vertical
contentItem: Rectangle {
implicitWidth: 6
implicitHeight: 100
radius: width / 2
color: control.pressed ? "#81e889" : "#c2f4c6"
}
}
}

Related

QML ScrollBar combined with ListView

I'm new to QML and QT so don't blame me if this question is going to sound stupid for most of you but I've search all over the internet without any luck in founding an answer.
What I'm trying to do:
I'm having a ScrollView which has inside of it a ScrollBar and a ListView.
I want that at the moment when I'm scrolling the ListView elements to also move the bar from ScrollBar. In other words, I want to use the ScrollBar as an overall view of your current position, you are not supposed to touch that, its only purpose is for viewing.
My Code:
ScrollView{
implicitHeight: 100
implicitWidth: 50
anchors.fill: parent
ScrollBar.horizontal: ScrollBar{
id: hbar
active: true
policy: ScrollBar.AlwaysOn
anchors {
left: parent.left
top: parent.top
right: parent.right
}
background: Rectangle {
implicitWidth: 100
implicitHeight: 50
opacity: enabled ? 1 : 0.3
color: hbar.down ? "#red" : "black"
}
contentItem: Rectangle {
implicitWidth: 6
implicitHeight: 100
radius: width / 2
color: hbar.pressed ? "#81e889" : "#c2f4c6"
}
}
ListView {
id: listViewParent
height: listViewID.height/10*6
contentHeight: height*2
contentWidth: width*2
clip: false
interactive: false
keyNavigationWraps: true
anchors.right: parent.right
anchors.rightMargin: 0
anchors.left: parent.left
anchors.leftMargin: 0
enabled: true
scale: 1
transformOrigin: Item.Center
anchors.verticalCenter: parent.verticalCenter
boundsBehavior: Flickable.DragAndOvershootBounds
flickableDirection: Flickable.HorizontalFlick
highlightMoveDuration: 0
cacheBuffer: 300
snapMode: ListView.SnapToItem
layoutDirection: Qt.LeftToRight
orientation: ListView.Vertical
model: 1
delegate:
ListView {
width: parent.width;
height: parent.height;
spacing: listViewID.width/8/9
model: MovieListModel {}
orientation: ListView.Horizontal
id: listid
delegate:
Rectangle {
property int recDynamicHeight: listViewID.height/10*6
property int recOriginalHeight: listViewID.height/10*6
property int recDynamiclWidth: listViewID.width/7
property int recOriginalWidth: listViewID.width/7
id: rectPer
width: recDynamiclWidth
height: recDynamicHeight
Image {
id: image1
anchors.fill: parent;
source: model.imgUrl
}
Text {
property bool isVisible: false
color: "#ffffff"
anchors.fill: parent
visible: textid.isVisible
id: textid
text: model.title
font.bold: true
horizontalAlignment: Text.AlignLeft
font.pixelSize: listViewID.width/8/9
topPadding: listViewID.width/8/9
leftPadding: listViewID.width/8/9
}
Text {
anchors.topMargin: listViewID.width/8/9
color: "#ffffff"
anchors.fill: parent
visible: textid.isVisible
id: yearId
text: model.year
horizontalAlignment: Text.AlignLeft
font.pixelSize: listViewID.width/8/9
topPadding: listViewID.width/8/9*2
leftPadding: listViewID.width/8/9
}
MouseArea {
anchors.fill: parent
onPressed: {
rectPer.recDynamicHeight = rectPer.recOriginalHeight;
rectPer.recDynamicHeight += rectPer.recOriginalHeight/10;
rectPer.recDynamiclWidth += rectPer.recOriginalWidth/10;
console.log(textid.isVisible);
textid.isVisible = true;
textid.visible = textid.isVisible;
console.log(sideButtonID.x);
console.log(sideButtonID.y);
console.log(model.year + " clicked");
}
onClicked: {
console.log("INDEX: " + model.id)
load_page(PageType.movie_detailed_view, model.title, model.description, model.imgUrl, model.type, model.year)
}
onReleased: {
rectPer.recDynamicHeight = rectPer.recOriginalHeight;
rectPer.recDynamiclWidth = rectPer.recOriginalWidth;
textid.isVisible = false;
textid.visible = textid.isVisible;
}
}
}
}
}
}
Layout:
You could try use a Flickable instead of a ScrollView and spawn a ListView there(delegates: Rectangles). Then, spawn the Scrollbar inside the ListView

Line numbers/ line height for a Qml TextArea

We want to implement an embedded code editor in our QtQuick based application. For highlighting we use a QSyntaxHighlighter based on KSyntaxHighlighting. We found no way to determine the line height and line spacing that would allow us to display line numbers next to the code. Supporting dynamic line-wrap would also be a great addition.
Flickable {
id: flickable
flickableDirection: Flickable.VerticalFlick
Layout.preferredWidth: parent.width
Layout.maximumWidth: parent.width
Layout.minimumHeight: 200
Layout.fillHeight: true
Layout.fillWidth: true
boundsBehavior: Flickable.StopAtBounds
clip: true
ScrollBar.vertical: ScrollBar {
width: 15
active: true
policy: ScrollBar.AlwaysOn
}
property int rowHeight: textArea.font.pixelSize+3
property int marginsTop: 10
property int marginsLeft: 4
property int lineCountWidth: 40
Column {
id: lineNumbers
anchors.left: parent.left
anchors.leftMargin: flickable.marginsLeft
anchors.topMargin: flickable.marginsTop
y: flickable.marginsTop
width: flickable.lineCountWidth
function range(start, end) {
var rangeArray = new Array(end-start);
for(var i = 0; i < rangeArray.length; i++){
rangeArray[i] = start+i;
}
return rangeArray;
}
Repeater {
model: textArea.lineCount
delegate:
Label {
color: (!visualization.urdfPreviewIsOK && (index+1) === visualization.urdfPreviewErrorLine) ? "white" : "#666"
font: textArea.font
width: parent.width
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
height: flickable.rowHeight
renderType: Text.NativeRendering
text: index+1
background: Rectangle {
color: (!visualization.urdfPreviewIsOK && (index+1) === visualization.urdfPreviewErrorLine) ? "red" : "white"
}
}
}
}
Rectangle {
y: 4
height: parent.height
anchors.left: parent.left
anchors.leftMargin: flickable.lineCountWidth + flickable.marginsLeft
width: 1
color: "#ddd"
}
TextArea.flickable: TextArea {
id: textArea
property bool differentFromSavedState: fileManager.textDifferentFromSaved
text: fileManager.textTmpState
textFormat: Qt.PlainText
//dont wrap to allow for easy line annotation wrapMode: TextArea.Wrap
focus: false
selectByMouse: true
leftPadding: flickable.marginsLeft+flickable.lineCountWidth
rightPadding: flickable.marginsLeft
topPadding: flickable.marginsTop
bottomPadding: flickable.marginsTop
background: Rectangle {
color: "white"
border.color: "green"
border.width: 1.5
}
Component.onCompleted: {
fileManager.textEdit = textArea.textDocument
}
onTextChanged: {
fileManager.textTmpState = text
}
function update()
{
text = fileManager.textTmpState
}
}
}
As you can see we use property int rowHeight: textArea.font.pixelSize+3 to guess the line height and line spacing but that of course breaks as soon as DPI or other properties of the system change.
The TextArea type has two properties contentWidth and contentHeight which contains the size of the text content.
So, if you divide the height by the number of lines (which you can get with the property lineCount), you will get the height of a line:
property int rowHeight: textArea.contentHeight / textArea.lineCount
But, if you plan to have multiple line spacing in the same document, you will have to handle each line by manipulating the QTextDocument:
class LineManager: public QObject
{
Q_OBJECT
Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged)
public:
LineManager(): QObject(), document(nullptr)
{}
Q_INVOKABLE void setDocument(QQuickTextDocument* qdoc)
{
document = qdoc->textDocument();
connect(document, &QTextDocument::blockCountChanged, this, &LineManager::lineCountChanged);
}
Q_INVOKABLE int lineCount() const
{
if (!document)
return 0;
return document->blockCount();
}
Q_INVOKABLE int height(int lineNumber) const
{
return int(document->documentLayout()->blockBoundingRect(document->findBlockByNumber(lineNumber)).height());
}
signals:
void lineCountChanged();
private:
QTextDocument* document;
};
LineManager* mgr = new LineManager();
QQuickView *view = new QQuickView;
view->rootContext()->setContextProperty("lineCounter", mgr);
view->setSource(QUrl("qrc:/main.qml"));
view->show();
Repeater {
model: lineCounter.lineCount
delegate:
Label {
color: "#666"
font: textArea.font
width: parent.width
height: lineCounter.height(index)
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
renderType: Text.NativeRendering
text: index+1
background: Rectangle {
border.color: "black"
}
}
}
I found a QML only solution:
Use TextEdit instead of TextArea to avoid alignment issues between line numbers and text
Use a 'ListView' to generate the line numbers for the text edit:
Here is an initial solution:
RowLayout {
anchors.fill: parent
ListView {
Layout.preferredWidth: 30
Layout.fillHeight: true
model: textEdit.text.split(/\n/g)
delegate: Text { text: index + 1 }
}
TextEdit {
id: textEdit
Layout.fillWidth: true
Layout.fillHeight: true
}
}
The ListView has a complete copy of each row of text. We can use this copy to compute the line height (taking into account of word wrap). We do this by creating an invisible Text. We can improve the answer further by adding a Flickable to the TextEdit and synchronize the scroll between the ListView and the TextEdit:
Here is a more complete solution:
// NumberedTextEdit.qml
import QtQuick 2.12
import QtQuick.Controls 2.5
Item {
property alias lineNumberFont: lineNumbers.textMetrics.font
property color lineNumberBackground: "#e0e0e0"
property color lineNumberColor: "black"
property alias font: textEdit.font
property alias text: textEdit.text
property color textBackground: "white"
property color textColor: "black"
Rectangle {
anchors.fill: parent
color: textBackground
ListView {
id: lineNumbers
property TextMetrics textMetrics: TextMetrics { text: "99999"; font: textEdit.font }
model: textEdit.text.split(/\n/g)
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.margins: 10
width: textMetrics.boundingRect.width
clip: true
delegate: Rectangle {
width: lineNumbers.width
height: lineText.height
color: lineNumberBackground
Text {
id: lineNumber
anchors.horizontalCenter: parent.horizontalCenter
text: index + 1
color: lineNumberColor
font: textMetrics.font
}
Text {
id: lineText
width: flickable.width
text: modelData
font: textEdit.font
visible: false
wrapMode: Text.WordWrap
}
}
onContentYChanged: {
if (!moving) return
flickable.contentY = contentY
}
}
Item {
anchors.left: lineNumbers.right
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.margins: 10
Flickable {
id: flickable
anchors.fill: parent
clip: true
contentWidth: textEdit.width
contentHeight: textEdit.height
TextEdit {
id: textEdit
width: flickable.width
color: textColor
wrapMode: Text.WordWrap
}
onContentYChanged: {
if (lineNumbers.moving) return
lineNumbers.contentY = contentY
}
}
}
}
}
I've found that you can query the line height using FontMetrics and then getting the true height by Math.ceil(fontMetrics.lineSpacing) for example:
TextEdit {
id: textArea
FontMetrics {
id: fontMetricsId
font: textArea.font
}
Component.onCompleted: {
console.log("Line spacing:" + Math.ceil(fontMetricsId.lineSpacing)
}
}

How to disable drag&drop for first Item of a ListView in QML

I have a QML project where I am able to drag & drop rectangles that are in a ListView.
I want to disable the drag&drop feature for the first Item (rectangle) of the ListView.
Here is an example:
Rectangle {
visible: true
width: 1000; height: 1000
ListView {
id: root
width: parent.width; height: parent.height
model: DelegateModel {
id: visualModel
model: myModel
model: ListModel {
id: colorModel
ListElement { someData }
...
}
delegate: MouseArea {
property int visualIndex: DelegateModel.itemsIndex
id: delegateRoot
cursorShape: Qt.PointingHandCursor
width: root.width; height: 100
drag.target: icon
drag.axis: Drag.YAxis
drag.minimumY: 0
property bool current: false
Rectangle {
blablaData
//Something like : if firstItem, disable drag&drop
}
onClicked: {
delegateRoot.current = !delegateRoot.current;
if(current) {
delegateRoot.height = 300
}
else {
delegateRoot.height = 100
}
}
Rectangle {
id: container
anchors.top: icon.bottom
width: root.width-5
height: delegateRoot.height - icon.height
clip: true
border.color: "#81BEF7"
Behavior on implicitHeight {
PropertyAnimation { duration: 100 }
}
Text {
anchors.fill: parent
anchors.margins: 10
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
text: size
}
}
DropArea {
anchors { fill: parent; margins: 15 }
onEntered: {
visualModel.items.move(drag.source.visualIndex, delegateRoot.visualIndex)
}
}
}
}
}
}
Do you have any idea of how to do it ?
Thanks a lot !
EDIT: Added some features to my example
In the delegate root item, try:
enabled: index ? true : false
I found an easy way to do it, and you can use it for the item you want (not only the first one).
I need to change drag.target and drag.axis in delegateRoot by using and setting a boolean like isDraggable to true or false on each item and then use it like this:
drag.target: isDraggable ? content : undefined
drag.axis: isDraggable ? Drag.YAxis : Drag.None

How to slide items in a ListView

I would like to create a slideshow showing 3 items with a picture and a label for each, the item in the middle being highlighted (picture is bigger and a description text appears below the label).
When a corresponding arrow is clicked, I would like the items to "slide" instead of just appearing where they should. Unfortunately, the Behavior on x {
NumberAnimation{...}} code in the delegate does not do this.
Here is my code:
import QtQuick 2.7
import QtQuick.Window 2.0
Window {
id: display
width: 500
height: 300
visible: true
Item {
id: conteneur
anchors.leftMargin: 50
height: display.height / 1.2
width: display.width / 1.2
anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
id: boutonAvant
height: conteneur.height
anchors.verticalCenter: parent.verticalCenter
width: 68
x: -50
color: "transparent"
z: 1
Text {
id: pictureAv
anchors.centerIn: parent
text: "<"
font.pixelSize: 90
}
MouseArea {
id: buttonAvMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: listview.decrementCurrentIndex()
}
}
ListView {
id: listview
clip: true
orientation: ListView.Horizontal
width: conteneur.width
height: conteneur.height / 1.2
anchors.centerIn: conteneur
model: myListModel
delegate: myDelegate
maximumFlickVelocity: 700
snapMode: ListView.SnapToItem
highlightFollowsCurrentItem: true
highlightRangeMode: ListView.StrictlyEnforceRange
preferredHighlightBegin: conteneur.width * 0.3
preferredHighlightEnd: conteneur.width * 0.3 + conteneur.width * 0.4
onCurrentIndexChanged: {
positionViewAtIndex(currentIndex, ListView.SnapPosition)
}
Component.onCompleted: {
currentIndex = 1
}
}
Rectangle {
id: boutonApres
height: conteneur.height
anchors.verticalCenter: parent.verticalCenter
x: conteneur.width - 10
width: 68
color: "transparent"
Text {
id: pictureAp
anchors.centerIn: parent
text: ">"
font.pixelSize: 90
}
MouseArea {
id: buttonApMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: listview.incrementCurrentIndex()
}
}
}
ListModel {
id: myListModel
ListElement {
name: "rectangle 0"
desc: "blabla"
mycolor: "green"
}
ListElement {
name: "rectangle 1"
desc: "blabla"
mycolor: "blue"
}
ListElement {
name: "rectangle 2"
desc: "blabla"
mycolor: "lightblue"
}
ListElement {
name: "rectangle 3"
desc: "blabla, \n with several lines for test \n and more lines \n and more lines"
mycolor: "gold"
}
}
Component {
id: myDelegate
Rectangle {
id: cadre
opacity: listview.currentIndex === index ? 1 : 0.5
anchors.top: parent.top
anchors.topMargin: listview.currentIndex === index ? 0 : 35
width: listview.currentIndex === index ? listview.width * 0.4 : listview.width * 0.3
height: conteneur.height
border.color: mycolor
color: "transparent"
Behavior on x {
NumberAnimation {
duration: 800
}
}
}
}
}
ListView inherits Flickable which uses contentX and contentY to govern what's visible. The model Rectangles don't actually move.
I would try a Behavior on ListView's contentX. Note that the documentation for positionViewAtIndex says not manipulate those directly because the math on them is not predictable – but a behavior on them may work.
I finally had some result using this :
//In bouton Avant :
MouseArea{
id: boutonAvant
anchors.fill: parent
hoverEnabled: true
onClicked: {
pictureAp.visible = true;
var oldPos = listview.contentX;
listview.decrementCurrentIndex();
var newPos = oldPos - listview.width*0.3; // listview.width*0.3 is the width of one item that is not the current one
if(listview.currentIndex == 0){
pictureAv.visible = false;
}
anim.running = false
anim.from = oldPos;
anim.to = newPos;
anim.running = true;
}
}
}
The ListView becomes :
ListView{
id: listview
clip: true
orientation: ListView.Horizontal
width: conteneur.width
height: conteneur.height/1.2
anchors.centerIn: conteneur
model: myListModel
delegate: myDelegate
Component.onCompleted: {
currentIndex = 1;
}
}
NumberAnimation { id: anim; target: listview; property: "contentX"; duration: 800 }
And boutonApres is similar to boutonAvant with :
MouseArea{
id: buttonApMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
pictureAv.visible = true;
var oldPos = listview.contentX;
listview.incrementCurrentIndex();
var newPos = oldPos + listview.width*0.3;
if(listview.currentIndex == listview.count-1){
pictureAp.visible = false;
}
anim.running = false
anim.from = oldPos;
anim.to = newPos;
anim.running = true;
}
}
It works fines when items being 'slided' are in the middle of the listview but when I get to the first item (on the last click on the left arrow), or to the last item (on the last click on the right arrow), I get a disturbing 'flick' as if the listview was trying to move at two places at the same time, following 2 different orders. But I can't see where this could come from...

QML : Drop-down menu that opens upward

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;

Resources