I am building a Qt5 application based on Qt-Quick 2 for the UI. I have an issue while displaying a ListView with an highlight component. When I scroll the ListView the highlight rectangle is visible outside of the ListView and I can't find a way to avoid it.
Here is an example of the issue with a minimal QML file:
import QtQuick 2.0
Rectangle {
width: 360; height: 600
ListView {
width: 350; height: 200
anchors.centerIn: parent
id: myList
model: myModel
highlight: highlightBar
delegate: Item {
width: 400; height: 20
Text { text: name }
MouseArea {
id: mArea
anchors.fill: parent
onClicked: { myList.currentIndex = index; }
}
}
}
Component {
id: highlightBar
Rectangle {
width: parent.width; height: 20
color: "#FFFF88"
}
}
ListModel {
id: myModel
}
/* Fill the model with default values on startup */
Component.onCompleted: {
for(var i = 0; i < 100; i++) {
myModel.append({ name: "Big Animal : " + i});
}
}
}
Is there a way to "limit" a component to its parent borders or to hide the highlight component while scrolling?
As reported by the documentation:
Note: Views do not enable clip automatically. If the view is not clipped by another item or the screen, it will be necessary to set clip: true in order to have the out of view items clipped nicely.
Hence, what you are experiencing is a common behaviour and you should either 1) clip the view via other Items (e.g. a header Rectangle and a footer Rectangle with z:infinite or simply set the clip property to true, i.e.
ListView{
//...
clip:true
//...
}
Clipping has some perfomance disavantages which can greatly affect the application as it grows. Hence, its usage, especially outside the views scenario, should be evaluated carefully.
Related
I tried to show origin image size in QML Image component,code like:
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
id: imageRect
width: parent.width
height: parent.height
anchors.fill: parent
DragHandler {
acceptedButtons: Qt.RightButton
target: sourceImage
xAxis.enabled: true
yAxis.enabled: true
}
Image {
id: sourceImage
source: "qrc:/2.jpg"
width: sourceSize.width
height: sourceSize.height
MouseArea {
width:parent.width
height:parent.height
onClicked: {
print(mouse.x, mouse.y)
print(sourceImage.x, sourceImage.y)
}
}
}
}
}
but the image is not fit with the parent's size, how can i fit the image to its parent and keep image origin size?
By default, the Image component will automatically set width and height to source image contents. You use this if you don't want any scaling to occur.
In the following example, I render the original Image, the Hubble view of the Pillars of Creation. I put it inside a Flickable with ScrollBars so that you can pan the image.
import QtQuick
import QtQuick.Controls
Page {
property string mouseInfo
Flickable {
id: flickable
anchors.fill: parent
contentWidth: image.width + 20
contentHeight: image.height + 20
clip: true
ScrollBar.vertical: ScrollBar {
width: 20
policy: ScrollBar.AlwaysOn
}
ScrollBar.horizontal: ScrollBar {
height: 20
policy: ScrollBar.AlwaysOn
}
Image {
id: image
source: "https://www.arcgis.com/sharing/rest/content/items/d0ecaa3fd9ef45c8ad255989ef6ded07/data"
MouseArea {
anchors.fill: parent
onClicked: mouseInfo = `${mouseX},${mouseY}`;
}
}
}
footer: Frame {
Text {
text: "image: %1x%2 mouseInfo:%3".arg(image.width).arg(image.height).arg(mouseInfo)
}
}
}
You can Try it Online!
I have a flow which fills up well beyond the bottom of the screen. So I wrapped it in a ScrollView; however, I just can't make it work.
A (minor) problem is that setting contentWidth to anything other than parent.width causes the flow to show nothing. I should NOT have to set contentWidth/contentHeight since the scrollView contains a single item. (But not setting these causes an empty scrollView).
The major problem is that the view is not scrollable (once I have content showing). I can see content cutoff on the bottom, but I can't drag it up/down with my mouse, nor does a scrollbar appear. What is wrong?
Rectangle {
anchors {
top: buttons.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
ScrollView {
clip: true
contentHeight: gatewayFlow.implicitHeight
contentWidth: parent.width // availableWidth // gatewayFlow.implicitWidth
Flow {
id: gatewayFlow
anchors.fill: parent
spacing: 10
Gateway { }
Gateway { }
Gateway { }
Gateway { }
Gateway { }
Gateway { }
Gateway { }
Gateway { }
Gateway { }
} // Flow
} // ScrollView
} // Rectange
The issue is that your ScrollView will by default grow and shrink its width and height to match the content size if you haven't otherwise constrained them. And if the width and height match the content width and height you naturally won't get any scrolling.
Add this to ScrollView to constrain it and get actual scroll behavior of the content:
anchors.fill: parent
I'm trying to understand the functionality of Behavior by animating a small Rectangle when it's property changes.
Consider the following example:
import QtQuick 2.4
import QtQuick.Controls 1.2
Item {
width: 600
height: 80
Rectangle {
id: rect
color: "red"
width: 20
height: 20
property int xval: 0
Behavior on xval {
NumberAnimation {
target: rect
property: "x"
to: rect.xval
duration: 2000
easing.type: Easing.InOutQuad
}
}
}
Button {
anchors.bottom: parent.bottom
onClicked: { rect.xval=250 }
}
}
Here I'm trying to animate the x property of the Item rect on Button Click. But it doesnot animate. Now if you replace
to: rect.xval
with
to: 400
The Rectangle animates as expected on Button Click. All I want to do is to animate the Rectangle using the value set by the user. Am I missing something ?
You don't need a extra property to animate a property.
Behavior on foo will animate foo whenever it changes its value and make it the implicit property of inner Animations.
Your code can simply be
Item {
width: 600
height: 80
Rectangle {
id: rect
color: "red"
width: 20
height: 20
Behavior on x {
NumberAnimation {
duration: 2000
easing.type: Easing.InOutQuad
}
}
}
Button {
anchors.bottom: parent.bottom
onClicked: { rect.x=250 }
}
}
I am trying to modify Gallery example. I want to add Button under TabView. So, I put TabView and Button into ColumnLayout, here is code:
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Window 2.0
Window {
visible: true
title: "settings"
width: 600
height: 400
ColumnLayout{
anchors.fill: parent
TabView {
anchors.right: parent.right
anchors.left: parent.left
Tab {
title: "Controls"
Controls { }
}
Tab {
title: "Itemviews"
Controls { }
}
Tab {
title: "Styles"
Controls { }
}
Tab {
title: "Layouts"
Controls { }
}
}
RowLayout{
anchors.right: parent.right
anchors.left: parent.left
Button{
text: "ok"
}
}
}
}
However, when I resize window okButton stands under tab controls. How should I fix code?
When you have defined a Layout, each element added has access to specific properties related to the layout itself. These properties are useful to position the element inside the space covered from the layout. Confront what is described here.
Hence, you should modify the ColumnLayout like this:
ColumnLayout {
anchors.fill: parent
TabView {
id:frame
enabled: enabledCheck.checked
tabPosition: controlPage.item ? controlPage.item.tabPosition : Qt.TopEdge
Layout.fillHeight: true // fill the available space vertically
Layout.fillWidth: true // fill the available space horizontally
Layout.row: 0 // item in the first row of the column
anchors.margins: Qt.platform.os === "osx" ? 12 : 2
Tab {
id: controlPage
title: "Controls"
Controls { }
}
Tab {
title: "Itemviews"
ModelView { }
}
Tab {
title: "Styles"
Styles { anchors.fill: parent }
}
Tab {
title: "Layouts"
Layouts { anchors.fill:parent }
}
}
Button {
text: "ok"
Layout.row: 1 // item in the second row of the column
Layout.alignment: Qt.AlignCenter // simple center the button in its spatial slot
}
}
You don't need a RowLayout for the button. It should be placed in the second row of the ColumnLayout you have defined, since it is a simple component. A sub-layout could be useful in case of multiple elements on the same row, e.g. two or more buttons.
Note also that anchoring is just used for the ColumnLayout to "stretch" and fit the window. All the other operations are executed via the layout properties. For general rules take a look at this other article.
I'm trying to highlight the currently selected item in a ListView. Below is the code I'm using; for some reason, while a similar code works perfectly in another ListView of this application, here the SelectedRectangle item is never displayed, althought the selected item changes when it should.
Rectangle {
id: deviceTree
width: (window.width * 2) / 3
height: 400
border {
width: 2
color: "black"
}
ListView {
id: deviceTreeView
model: deviceTreeModel
delegate: deviceTreeDelegate
highlight: SelectionRectangle {}
anchors.fill: parent
anchors.margins: 6
}
Component {
id: deviceTreeDelegate
Rectangle {
border.color: "#CCCCCC"
width: deviceTree.width
height: 30
smooth: true
radius: 2
MouseArea {
anchors.fill: parent
onClicked: { deviceTreeView.currentIndex = index; window.selectedDeviceChanged(deviceName) }
}
}
}
}
SelectedRectangle.qml
Rectangle
{
id: selectionRectangle
color: "lightsteelblue"
smooth: true
radius: 5
}
SOLUTION: The rectangle in deviceTreeDelegate was by default white and overlapped the selection rectangle. Using the property it's set as trasparent so that the selection can be seen.
This is due to the default Rectangle color being white and the highlight being stacked under the delegate. Setting the Rectangle color to "transparent" will allow the highlight to be visible through the delegate.
Your code gets two mistakes :
The component for the highlight property. The name of the type of the component is the same than the name of the QML file where it is defined. You defined it in a file named SelectedRectangle.qml so you have to write highlight: SelectionRectangle {} in your main QML file
The type of the highlight member is Component. So the component that you use for this member should have got a type which inherits Component. Or you use a QML component that inherits Rectangle and Rectangle does not inherit Component. You should enclose your SelectedRectangle in a Component object, just like you did for the delegate.
Finally, you should write something like this for your highlight component :
highlight: Component {
SelectedRectangle {}
}