So I have an Image inside a Flickable. I want to know the size of the image after the scale is applied so that I can assign it to the Flickable's contentWidth and contentHeight. Is there a way to get the size after the scale has been applied?
Flickable{
contentWidth: target.width
contentHeight: target.height
Image{
id: target
horizontalAlignment: Image.AlignLeft
verticalAlignment: Image.AlignTop
fillMode: Image.PreserveAspectFit
scale: slider_bar.value
source: "/image.png"
}
}
Slider{
id: slider_bar
from: 0
to : 2
value: 1
}
Another example is where I want to make the rect_1 large and the rect_2 to stay to the right of it. When running the following rect_1 resizes but rect_2 does not move.
Rectangle{
id:rect_1
height: 100
width: 100
scale: slider_bar.value
transformOrigin: Item.TopLeft
color: "green"
}
Rectangle{
id: rect_2
anchors.left: rect_1.right
height: 100
width: 100
color:"red"
}
Slider{
id: slider_bar
from: 0
to : 2
value: 1
}
I could do something like
ScaledItem.qml
Item{
height: implicitHeight
width:implicitWidth
implicitHeight: childrenRect.height * scale
implicitWidth: childrenRect.width * scale
scale:1
}
then
ScaledItem{
scale: slider_bar.value
transformOrigin: Item.TopLeft
id:rect_1
Rectangle{
height: 100
width: 100
color: "green"
}
}
Rectangle{
anchors.left: rect_1.right
height: 100
width: 100
color:"red"
}
Slider{
id: slider_bar
from: 0
to : 2
value: 1
}
Related
I'm trying to create a reusable slider. I'm having trouble to set implicit sizes correctly so that the CustomSlider includes the Slider and the Label. I would like to have a implicit size specified, but let the user set a width for the slider itself.
I tried using childrenRect but that gives me a binding loop error.
How can I have the yellow background span across all the components: the slider and the green label?
Currently:
Would like:
CustomSlider.qml
Item {
id: root
property int startval: 0
property int endval: 20
property int sliderWidth: 200
// This results in binding loop
//implicitHeight: childrenRect.height
implicitHeight: control.height + label.height
implicitWidth: sliderWidth
Rectangle {
color: "yellow"
width: root.width
height: root.height
}
Slider {
id: control
stepSize: 1
anchors.centerIn: parent
snapMode: Slider.SnapOnRelease
width: root.sliderWidth
from: root.startval
to: root.endval
handle: Rectangle {
id: handleId
x: control.visualPosition * (control.width - width)
y: (control.height - height) / 2
width: 20
height: 20
radius: 20
color: "gray"
}
background: Rectangle {
y: (control.height - height) / 2
height: 4
radius: 2
color: "green"
Rectangle {
width: control.visualPosition * parent.width
height: parent.height
color: "red"
radius: 2
}
}
}
Label {
id: label
width: 20
height: 20
text: control.value
font.pixelSize: 15
color: "black"
x: handleId.x + control.x
y: handleId.y - 20
Rectangle {
color: "green"
anchors.fill: parent
opacity: 0.3
}
}
}
Main.qml
CustomSlider {
anchors.centerIn: parent
startval: 0
endval: 10
//sliderWidth: 100
}
I usually set the Width and height based on the parent.
I set sliderWidth: parent.width/2.0 and for your green label I add TextMetrics and calculate its width based on the text that it wants to show.
import QtQuick 2.15
import QtQuick.Controls 2.15
Item {
id: root
property int startval: 0
property int endval: 0
property int sliderWidth: parent.width/2.0
// This results in binding loop
//implicitHeight: childrenRect.height
implicitHeight: control.height + label.height
implicitWidth: sliderWidth
Rectangle {
color: "yellow"
width: root.width
height: root.height
}
Slider {
id: control
stepSize: 1
anchors.centerIn: parent
snapMode: Slider.SnapOnRelease
width: root.sliderWidth
from: root.startval
to: root.endval
handle: Rectangle {
id: handleId
x: control.visualPosition * (control.width - width)
y: (control.height - height) / 2
width: 20
height: 20
radius: 20
color: "gray"
}
background: Rectangle {
y: (control.height - height) / 2
height: 4
radius: 2
color: "green"
Rectangle {
width: control.visualPosition * parent.width
height: parent.height
color: "red"
radius: 2
}
}
}
Label {
id: label
width: t_metrics.tightBoundingRect.width +4
height: t_metrics.tightBoundingRect.height +7
text: control.value
font.pixelSize: 15
color: "black"
x: handleId.x + control.x
y: handleId.y - 20
Rectangle {
color: "green"
anchors.fill: parent
opacity: 0.3
}
}
TextMetrics {
id: t_metrics
text: control.value.toString()
}
}
Updated:
in CustomSlider.qml , changed it to this code:
import QtQuick 2.15
import QtQuick.Controls 2.15
Item {
id: root
property int startval: 0
property int endval: 0
property int sliderWidth: parent.width/2.0
implicitHeight: control.height + label.height
implicitWidth: sliderWidth
Rectangle {
color: "yellow"
width: root.width +10
height: root.height +control.height + label.height + t_metrics.tightBoundingRect.height +7
Slider {
id: control
stepSize: 1
anchors.centerIn: parent
snapMode: Slider.SnapOnRelease
width: root.sliderWidth
from: root.startval
to: root.endval
handle: Rectangle {
id: handleId
x: control.visualPosition * (control.width - width)
y: (control.height - height) / 2
width: 20
height: 20
radius: 20
color: "gray"
}
background: Rectangle {
y: (control.height - height) / 2
height: 4
radius: 2
color: "green"
Rectangle {
width: control.visualPosition * parent.width
height: parent.height
color: "red"
radius: 2
}
}
}
Label {
id: label
width: t_metrics.tightBoundingRect.width +4
height: t_metrics.tightBoundingRect.height +7
text: control.value
font.pixelSize: 15
color: "black"
x: handleId.x + control.x
y: handleId.y /2 + 4
Rectangle {
color: "green"
anchors.fill: parent
opacity: 0.3
}
}
TextMetrics {
id: t_metrics
text: control.value.toString()
}
}
}
This makes your text label shows inside the yellow rectangle and in main.qml I add one Row with labels and spinboxes for the test.
If you want that user to set sliderWidth or startval and endval and then show him Slider you need to create that object dynamically.
and if you want to be displayed in the Column and don't overlap you need ColumnLayout.
If you want to scroll them then you need to use ScrollView.
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
Window {
width: 660
height: 480
visible: true
title: qsTr("Hello World")
ScrollView {
width: parent.width
height : parent.height
contentWidth: slidersColumn.width
contentHeight: slidersColumn.height
clip : true
ColumnLayout {
id: slidersColumn
anchors.fill: parent
spacing:50
}
}
function addSlider(sliderWidth,startval,endval) {
var obj = Qt.createComponent("CustomSlider.qml");
var slider = obj.createObject(slidersColumn);
slider.startval=startval;
slider.endval=endval;
slider.sliderWidth=sliderWidth;
}
Row
{
x: 0
y: 5
width: parent.width
height: 30
Label {
id: lbl_slider_width
text: qsTr(" Slider width ")
}
SpinBox {
id: spinBox_slider_width
editable: true
from:0
to:parent.width
}
Label {
id: lbl_startval
text: qsTr(" Startval ")
}
SpinBox {
id: spinBox_startval
editable: true
from:0
to:parent.width
}
Label {
id: lbl_endval
text: qsTr(" Endval ")
}
SpinBox {
id: spinBox_endval
editable: true
from:0
to:parent.width
}
Button {
id: button
text: qsTr(" Create Slider")
onClicked:
{
addSlider(spinBox_slider_width.value,spinBox_startval.value,spinBox_endval.value)
}
}
}
}
The result is:
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 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 need to create a long form using QML. The form will not fit inside the window, so I need for it to be scrollable. However I can't get the scroll view to work. Here is a minimum working example of my problem:
import QtQuick.Window 2.2
import QtQuick 2.9
import QtQuick.Controls 2.3
Window {
visible: true
width: 1280
height: 720
title: qsTr("Hello World")
Rectangle{
anchors.centerIn: parent
width: parent.width*0.8;
height: parent.height*0.7;
ScrollView {
anchors.fill: parent
clip: true
contentHeight: parent.height
Rectangle{
id: rect1
width: parent.width
height: 200
color: "#ffff00"
anchors.horizontalCenter: parent.horizontalCenter
}
Rectangle{
id: rect2
width: parent.width
height: 500
color: "#ff00ff"
anchors.top: rect1.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
Rectangle{
id: rect3
width: parent.width
height: 500
color: "#00ffff"
anchors.top: rect2.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
As I understand it, this should allow me to scroll in order to see the 3 rectangles. However I only the see the first one and the upper half of the second one and I can't scroll.
Any help would be greatly appriciated
Because your ScrollView contains multiple items you need to take care of sizing yourself and set contentHeight explicitly to the combined height of all the items.
For testing, you can set vertical scrollbar always on to see how content height affects the scrollbar.
I commented out horizontal center anchoring because it is not needed (width of your rectangles is scrollview width).
ScrollView {
anchors.fill: parent
clip: true
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
contentHeight: rect1.height+rect2.height+rect3.height
Rectangle{
id: rect1
width: parent.width
height: 200
color: "#ffff00"
//anchors.horizontalCenter: parent.horizontalCenter
}
Rectangle{
id: rect2
width: parent.width
height: 500
color: "#ff00ff"
anchors.top: rect1.bottom
//anchors.horizontalCenter: parent.horizontalCenter
}
Rectangle{
id: rect3
width: parent.width
height: 500
color: "#00ffff"
anchors.top: rect2.bottom
//anchors.horizontalCenter: parent.horizontalCenter
}
}
If you wrap your rectangles with an item and set item implicitHeight to its height ScrollView detects the contentHeight correctly.
ScrollView {
anchors.fill: parent
clip: true
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
Item {
width: parent.width
height: rect1.height+rect2.height+rect3.height
implicitHeight: height
Rectangle{
id: rect1
width: parent.width
height: 200
color: "#ffff00"
}
Rectangle{
id: rect2
width: parent.width
height: 500
color: "#ff00ff"
anchors.top: rect1.bottom
}
Rectangle{
id: rect3
width: parent.width
height: 500
color: "#00ffff"
anchors.top: rect2.bottom
}
}
}
The default implicit size for most items is 0x0, that's why you have to set implicit height for the item explicitly. However some items have an inherent implicit size, e.g. Image and Text. This means that if you place e.g. TextArea into your ScrollView it will automatically become scrollable if text is long enough.
ScrollView {
anchors.fill: parent
clip: true
TextArea {
readOnly: true
text: online ? provider.loadedText : "Offline"
wrapMode: Text.WordWrap
}
}
Set the height and width of the scrollview to be the total of childs height added together!
I have a list view which need to be masked by an image.
Because am using a highlight component whose width need to be reduced according to the scrolling.
Is it possible with this code ? If anything wrong in this please suggest me some methods.
Item{
id: test
x: 0
y: 0
width: 1920
height: 720
ListView {
id: source_list
x: 0
y: 0
width: 600
height: 720
spacing: 40
model: mediaSongsModel
delegate: mediaSongsDelegate
focus: true
interactive: true
highlightFollowsCurrentItem: true
highlightMoveDuration: 0
highlight: highlightBar
snapMode: ListView.SnapOneItem
preferredHighlightBegin:260/scaleFactor
preferredHighlightEnd: 260/scaleFactor
highlightRangeMode : ListView.ApplyRange
}
layer.enabled: true
layer.effect: OpacityMask {
maskSource:Item {
width: 100
height: 500
Image{
id :crop
x: 0
y: 0
width: 600
height: 720
source :"image/bg.png"
}
}
}
}
Something as you already did:
import QtQuick 2.7
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0
Window {
visible: true
width: 600
height: 600
Rectangle {
id: rect
width: 400
height: 400
anchors.centerIn: parent
color: "black"
visible: (img.status == Image.Ready)
ListView {
anchors.fill: parent
model: 30
delegate: Text { text: "itemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm" + index; color: "yellow" }
}
layer.enabled: true
layer.effect: OpacityMask {
maskSource: img
}
}
Image {
id: img
source: "https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/1024px-Google_%22G%22_Logo.svg.png"
width: 400
height: 400
anchors.centerIn: parent
visible: false
}
}
But I don't think you can mask mouse events.