QML SplitView - manually resize childs - qt

I have a QtQuick Controls 1.3 SplitView(as I am on QT 5.11), which contains 3 rectangles in vertical orientation. It displays fine, and I can drag-resize the childs as intended.
Now I want to add a button which allows the user to completely hide the bottom most rectangle, effectively collapsing it. However, nothing I am trying to resize the rect works:
import QtQuick.Controls 1.3 as C1
[...]
C1.SplitView {
id: splitView
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
width: parent.width - flightSelector.width - separator.width
orientation: Qt.Vertical
LateralChart {
id: lateralChart
width: parent.width
height: mainPage.height * 0.75
Layout.minimumHeight: 30
Layout.maximumHeight: mainPage.height - 30 - 30
}
UtilityBar {
id: utilityBar
Layout.minimumHeight: 30
Layout.maximumHeight: 30
onCollapse: {
console.log("minimize")
flightList.height = 0 // no effect
flightList.preferredHeight = 0 // no effect
flightlist.Layout.maximumHeight = 0 // no effect
flightList.shouldCollapse = true // no effect
}
}
FlightListTable {
id: flightList
width: parent.width
Layout.minimumHeight: 0
Layout.maximumHeight: mainPage.height - 60 - 30
model: flightListFilterModel
property bool shouldCollapse: false
C1.SplitView.preferredHeight: shouldCollapse ? 0 : 300
}
}
[...]
If I just go flightList.visible = false, then the rect will be hidden, but the position of the middle rect remains, so it is positioned wrong (it should move to the bottom).
How can I resize SplitView child contents dynamically via JS code?

According to the docs, there must always be one (and only one) child object that has Layout.fillheight set to true. By default, it will choose the last visible child in the SplitView. In your case, it sounds like you want that to actually be the first child. So adding Layout.fillHeight: true to your LateralChart should give you the desired output.

Related

TestCase mouseDrag only clicks item inside Flickable but does not drag

In a QML TestCase, I'm trying to setup automatic scrolling of a ListView that is contained inside a Flickable (to add a custom footer that can be flicked into view, which wouldn't happen with just ListView { footer: Component {} })
However, the mouseDrag only seems to click the correct coordinate, but not drag it to any direction. Here is a simplified version that is as close to the real one as possible:
Implementation.qml
import QtQuick 2.5
FocusScope {
width: 1920
height: 1080
Flickable {
objectName: 'flickableList'
boundsBehavior: Flickable.StopAtBounds
clip: true
width: parent.width
height: 240
contentHeight: 500
ListView {
interactive: false
height: parent.height
width: parent.width
model: ['example1', 'example2', 'example3', 'example4', 'example5']
delegate: Item {
width: 300
height: 100
Text {
text: modelData
}
}
}
}
Item {
id: footer
height: 100
width: parent.width
}
}
TheTest.qml
// The relevant part
var theList = findChild(getView(), 'flickableList')
var startY = 220
var endY = 20
mouseDrag(theList, 100, startY, 100, endY, Qt.LeftButton, Qt.NoModifier, 100)
So, when I'm viewing the UI testrunner, I can see it clearly click on the correct delegate (it has a focus highlight in the actual implementation), ie. the third item "example3", which starts at Y 200 and ends at Y 300). But the drag event never happens. Nothing moves on the screen, and compare(theList.contentY, 200) says it is still at position 0. I would expect it to be at 200, since the mouse is supposed to be mouseDragging from position 220 to 20, ie. scrolling the list down by 200. And 220 is also within the visible height (240).
Just to be sure, I also reversed the Y values, but also no movement:
var theList = findChild(getView(), 'flickableList')
var startY = 20
var endY = 220
mouseDrag(theList, 100, startY, 100, endY, Qt.LeftButton, Qt.NoModifier, 100)
Also, as the 3rd item clearly is clicked on (it gets highlighted), the passed item theList (= the Flickable), should be valid.
Edit:
Oh, and this does scroll the list, but it goes all the way to the bottom of the list (388 px down in the actual implementation, even when the delta is just 30 pixels):
mousePress(theList, startX, startY)
mouseMove(theList, endX, endY)
mouseRelease(theList, endX, endY)
So the question is:
Does mouseDrag only work for specific types of components (ie. does not work on Flickable?), or is there something missing? How can I get it to scroll the list down? Thanks!
Your tag says you're using Qt 5.5 - I would recommend trying Qt 5.14 if possible, as there was a fix that might help:
mouseDrag(): ensure that intermediate moves are done for all drags
[...]
In practice, this means that mouseDrag() never did intermediate moves
(i.e. what happens during a drag in real life) for drags that go from
right to left or upwards.
https://codereview.qt-project.org/c/qt/qtdeclarative/+/281903
If that doesn't help, or upgrading is not an option, I would recommend looking at Qt's own tests (although they are written in C++):
https://code.qt.io/cgit/qt/qtdeclarative.git/tree/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp#n1150
I think mouseDrag only works for mouse area. You could wrap every object with that.
But in the end, you need to use a mouse area inside you delegate and Drag and Drop it.
https://doc.qt.io/qt-5/qml-qtquick-drag.html
import QtQuick 2.5
FocusScope {
width: 1920
height: 1080
Flickable {
objectName: 'flickableList'
boundsBehavior: Flickable.StopAtBounds
clip: true
width: parent.width
height: 240
contentHeight: 500
ListView {
interactive: false
height: parent.height
width: parent.width
model: ['example1', 'example2', 'example3', 'example4', 'example5']
delegate: DelegateList{
textAreaText = modelData
}
}
}
Item {
id: footer
height: 100
width: parent.width
}
}
And the DelegateList.qml
Item {
id: root
property alias textAreaText: textArea.text
width: 300
height: 100
Text {
id: textArea
}
Drag.active: dragArea.drag.active
Drag.hotSpot.x: 10
Drag.hotSpot.y: 10
MouseArea {
id: dragArea
anchors.fill: parent
drag.target: parent
}
}

QML Scroll View does not allow scrolling of its content

I need to create components dynamically add added to an area of the screen that, of course, needs to be scrollable. I found out that no matter how many of components I added with the scroll bar as its parent, the scroll bars would not appear and the element would not be scrollable.
I did a little fiddling and I think I came up with a minum working example of what I am talking about:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ScrollView {
width: 200
height: 200
clip: true
Label {
text: "ABC"
font.pixelSize: 224
}
// Rectangle {
// color: "#ff0000"
// width: 100
// height: 100
// }
}
}
This is a modified version of the example used int he official documentation. However when I uncomment the square the screen is no longer scrollable (scroll bars never appear).
If I remove the label and leave the rectangle (making it larger so that there is something to scroll to) it still doesn't work.
I am using Qt 5.10.
So the code below worked for me. I defined a rectangle as a backgroud to get border lines to a scrollable table that I need to create.
Rectangle {
id: tableBackground
color: "#ffffff"
border.width: 2
border.color: "#EDEDEE"
radius: 4
anchors.top: tableHeader.bottom
anchors.left: tableHeader.left
width: vmTableWidth
height: vmTableHeight - tableHeader.height
ScrollView {
id: tableArea
anchors.fill: parent
clip: true
ListView {
id: patientListView
anchors.fill: parent
model: patientList
delegate: VMPatientEntry {
onFetchReport: {
// This is a signal emitted by my VMPatientEntry.
}
}
onCurrentIndexChanged: {
// Do stuff when the current index changes.
}
}
}
}
So I hope this answer allows someone to fix their problem as well.

Can We have a SwipeView by using PathView?

In QML Swipe View is not bidirectional.So I need a swipe view
A code sample will be very beneficial for me.
I need to keep only 3 items in my view & at a time only item should be visible & on swiping the view in either way left or right element should be on center.
This code solves half problem That is why I posted as answer
import QtQuick 2.0
Item {
property alias model: view.model
property alias delegate: view.delegate
property alias currentIndex: view.currentIndex
property real itemHeight: 60
clip: true
PathView {
id: view
anchors.fill: parent
snapMode: PathView.NoSnap
pathItemCount: height/itemHeight
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
dragMargin: view.width/5
path: Path {
startY: view.width/4; startX:-itemHeight/2 -50
PathLine { y: view.width/4; x: (view.pathItemCount*itemHeight + 3*itemHeight) }
}
}
}
And this is My Item :
Item{
id:widgetMain
width :480
height : 240
property int delegateHeight: widgetMain.height
property int delegateWidth : widgetMain.width
Spinner {
id: spinner
width: parent.width;
height: parent.height;
focus: true
model: ["qrc:/Tile1.qml",
"qrc:/Tile2.qml"
,"qrc:/Tile3.qml"]
itemHeight: 150
delegate: Loader {
width: delegateWidth
height: delegateHeight
source: modelData
}
}
}
Now If I swipe towards any direction, It shows only 1 tile in the view. & When my drag reaches to half way, then the tile removes & shifts to last.
Here I want to display that one tile is swiping & 2nd tile is coming from behind(Just like a Swipe view).
Now can you help me please?

How to scroll list view to the current item?

I have a list view. If i click on a cell, that specific cell need to move to the center with a small scrolling animation. With my code, the clicked cell will comes to the center without any animation.
Is it possible to add animation for that ?
Am putting my code below :
ListView {
id: source_list
width: 1080
height: 480
spacing: 50
model: mediaSongsModel
delegate: mediaSongsDelegate
focus: true
interactive: true
clip: true
highlightMoveDuration: 50
snapMode: ListView.SnapToItem
boundsBehavior:Flickable.StopAtBounds
preferredHighlightBegin: 260/scaleFactor
preferredHighlightEnd: 260/scaleFactor
highlightRangeMode: ListView.StrictlyEnforceRange
}
Component {
id: mediaSongsDelegate
Item {
id: wrapper
width: 1080
height: 200
MouseArea {
anchors.fill: parent
onClicked: {
source_list.currentIndex = index
source_list.positionViewAtIndex(index,ListView.Center)
}
}
}
}
If the current item should always be in the center or within a specific are of the view, then you can use the preferredHighlightBegin and preferredHightlightEnd properties to define that area.
The value of highlightRangeMode controls if and if yes, how strictly this applies. E.g. if the first item is the current item and the value is StriclyEnforeRange then the item will be within the specified area even if that means scrolling further up than a normal "scroll to top" would.
Something like that should work
ListView {
preferredHighlightBegin: height / 2 - 100 // 100 being item height / 2
preferredHighlightEnd: height / 2 + 100 // 100 being item height / 2
highlightRangeMode: ListView.StrictlyEnforceRange
}
I've solved my issue by removing the following line of code:
source_list.positionViewAtIndex(index,ListView.Center);
The animation correctly worked.

How I can dropdown options when I check on checkbox?

I have one Checkbox with onCheckedChanged handler and what I want is, when the Checkbox is checked, dropdown a menu with several texts and text fields. I have the following code:
CheckBox {
id: box
onCheckedChanged: {
// TODO here to dropdown a menu with settings
}
}
I have texts and text fields like the following:
Component {
id: label
Text {
color: "red"
antialiasing: true
smooth: true
}
}
I'm a newbie in QML so please be patient.
You didn't really say where this menu is located, if it's floating or if it is to just appear maybe displacing other elements on the view. Anyway, to anwser your question, you can achieve what you're asking by setting the height of your 'menu' to zero then, when the CheckBox is checked, setting it to however tall you want it to be. To make the menu grow smoothing you can use a NumberAnimation.
You can change your onCheckedChanged() slot to look like this:
onCheckedChanged: {
menu.height = checked ? 100 : 0
}
and add the following, as a child of your menu element:
Behavior on height { NumberAnimation {...} }
to make the menu's height grow from 0 to 100 over a period of time to make it grow smoothly.
Another approach, which I'd prefer, is to use States with a Transition (instead of a Behavior).
Here is an example of a 'menu' which, when the CheckBox is checked, will slide out from beneath the CheckBox:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
ApplicationWindow {
title: qsTr("Hello World")
width: 640
height: 480
visible: true
Rectangle {
id: checkboxContainer
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: 100
color: "pink"
CheckBox {
id: menuCheckBox
anchors.centerIn: parent
text: qsTr("Click Me")
}
}
Rectangle {
id: menu
anchors.top: checkboxContainer.bottom
anchors.left: parent.left
anchors.right: parent.right
height: 0 //This is the default value when the 'default' state is active. That is whenever we're not in the "openState"
clip: true // this hurts rendering performance a bit but is required to make sure child elements don't exceed the bounderies of this object (so when height is zero you don't see the text)
color: "lightblue"
states: [
State {
name: "openState"
when: menuCheckBox.checked // This state is only active when the check box is checked. When you uncheck the check box we move to the 'default' state (which sets the menu's hight back to zero)
PropertyChanges {
target: menu
height: 100
}
}
]
transitions: Transition {
NumberAnimation {
property: "height"
duration: 350 //This means when the height property is changed it will take 350ms to move from what its at to what your changing it to (i.e. 0 to 100 or 100 to 0).
easing.type: Easing.InOutQuad
}
}
Text {
anchors.centerIn: parent
color: "red"
antialiasing: true
smooth: true
text: qsTr("HELLO")
}
}
}
I hope this answers your question.

Resources