How to display/mask part of an Image without scaling - QtQuick/QML - qt

I'm trying to make a simple audio meter with QtQuick. The meter graphic comes from a PNG file, and when the level changes, I want to change the height of the displayed part of the image, without scaling it at all. I simply want to mask some of the image off without changing it.
I have tried the following code:
import QtQuick 2.0
Rectangle {
width: 360
height: 482
Image {
x: 165
source: "meter.png"
fillMode: Image.Pad
anchors.bottom: parent.bottom
height: 482
}
Image {
x: 175
source: "meter.png"
fillMode: Image.Pad
anchors.bottom: parent.bottom
height: 440
}
Image {
x: 185
source: "meter.png"
fillMode: Image.Pad
anchors.bottom: parent.bottom
height: 400
}
}
But this gives the following undesried results, with some kind of scaling happening. I want where the yellow and green meet in all 3 images to be identical.

The Image component fills from top to bottom by default, but instead of wrapping Image in an outer Item, and using clip which is bad for performance, just add to all your Image items :
width: sourceSize.width; // to be sure the width is the exact same as the source
verticalAlignment: Image.AlignBottom; // to force image to start from the bottom
So the content will not be scaled and aligned to the bottom of your Image.

The Image Item fills its content top-down, so if you want to anchor it to the bottom you will need an additional container Item to clip out the Image's top portion:
Item {
x: 165
width: childrenRect.width
height: 482
clip: true // This is the key
Image {
source: "meter.png"
anchors.bottom: parent.bottom
}
}

Related

Set height of popup to contain contents

I want to set the size (mainly height) of my popup to fit the contents depending on how much text is shown or whether there's an icon image shown on popup. How do I set the height of popup.
Eg.
Popup {
id: popup
width: window.width/2
height: window.height/4
x: window.width/2 - width/2
y: window.height/2 - height/2
Rectangle {
id: popupContent
width: parent.width
height: parent.height
visible: notification
anchors.fill: parent
Rectangle {
id: iconField
anchors.top: parent.top
width: parent.width
height: parent.height/2
Image {
id: img
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
width: window.width/18
height: window.width/18
fillMode: Image.PreserveAspectFit
source: "qrc:/images/icons/info.png"
}
}
Rectangle {
id: textField
anchors.top: iconField.bottom
width: parent.width
height: parent.height/2
Text {
id: text1
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignHCenter
width: parent.width
wrapMode: Text.WordWrap
text: "This long text overflows out of the popup up rectangle!"
}
}
}
}
If I use a long text then the text overflows from the popup rectangle. I tried using implicitHeight in different places but I don't understand how to apply it in this situation.
There's several issues with your code. It's hard to make a perfect answer because I don't know exactly what's intended. For example, your text will always be off the bottom of the Rectangle because you anchored textField's anchor.top to iconField.bottom, and iconField is the same size as the entire popup. But here's some ideas on how to improve it.
Your popupContent is a Rectangle, but I'm not sure if you actually are intending to draw a rectangle there or not. I think you could replace that with a ColumnLayout like the example here.
You can also manually specify the height of your content using the contentHeight property. You could set it to the height of your iconField plus the height of your textField, plus any padding you want.
Every Item has a property called childrenRect.height which will tell you the combined height of all of its children.
For all of these options though, you will need to stop setting every object's height to be the same as its parent's height.

How can i set text align from bottom to top in qml?

I have a background image a and i want to right the text align from bottom to top.Just like the image showed as following. In my case, the background image is fixed, i cannot rotate it,so i just tried to rotate text!However, i cannot align it well!
Background Image(cannot be rotated)
The result i want(just like left align,center align and rotate -90)
I tried this code,but not work! I think the reason is the rotation center!
Text {
text: name;
anchors.verticalCenter: parent.verticalCenter; // Centering text
anchors.left: parent.left;
anchors.leftMargin: 18;
rotation: -90
}
If i rotate the background image 90 degree. Then apply my code and rotate the content(background and text) will get good result! However i cannot rotate the background image! How can i set text align from bottom to top in qml?
Anchoring with rotation might be at odds to manage. You can make it simple:
Rectangle{
color: "grey"
width: 50
height: 300
Text{
//1. Place Text box symmetrically below background, edge to edge
width: parent.height
height: parent.width
y:parent.height
text: "TableA Description 15"
verticalAlignment: Text.AlignVCenter
// comment below 2 lines to see how it looks before rotation
//2 pivot top left of text box and rotate text -90
transformOrigin: Item.TopLeft
rotation: -90
}
}
Transform provides more complex transformations for the QML item. In your case, check demo in below, it shows Text rotate itself -90 degree. and you can adjust the rotate point by setting the origin.x origin.y properties.
Rectangle{
width: 100; height: 300
color: "lightblue"
Text{
id: test
text: "TestMe"
transform: [
Rotation {
origin.x: test.paintedWidth/2; origin.y: test.paintedWidth/2; angle: -90
},
Translate{
y: (test.parent.height - test.paintedWidth)/2
}
]
}
}

Wrong width and position of non-attached horizontal QML ScrollBar (and ScrollIndicator) when I resize parent element from RTL

The problem is in position and width of the horizontal scrollbar and position of the content that has been scrolled when I resize the width of the window (parent) element in RTL direction.
When I do these steps:
Resize the width of window in LTR direction.
Everything is working fine.
Change scrollbar position to any other position that is different from 0.0, (for example move it all the way to the right side)
Resize the width of window in opposite (RTL) direction
Scrollbar starts to behave odd and scrollable content is in the wrong position
I get this situation:
Width of scrollbar's contentItem (aka scrollbar's handle) is wrongly calculated.
Scrollbar's position is also wrongly calculated
The content is not scrolled to the right place (property "x" of scrollable content is wrongly calculated )
What I want is that:
the width of scrollbar's contentItem (aka scrollbar's handle) increases proportionately as the width of the window increases
the content (which was in the position that its right side was completely visible) should stay in that position. And with the expansion of the window, on the left side, the other part of the content that was not visible until then, should start to show up.
The same things are happening if I try to use non-attached QML ScrollIndicator.
This seams to be the bug in QML, and I have reported it, but I need the solution now... If anyone could help, it would be great. Thanks!
import QtQuick 2.7
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
Window
{
id: main
width: 400
height: 200
Rectangle
{
id: frame
clip: true
anchors.fill: parent
color: "purple"
Text
{
id: content
text: "ABCDE"
font.pixelSize: 160
x: -hbar.position * width
}
ScrollBar
{
id: hbar
hoverEnabled: true
active: true
policy: ScrollBar.AlwaysOn
visible: size < 1
orientation: Qt.Horizontal
size: frame.width / content.width
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
background: Rectangle
{
color: "black"
}
}
}
}
scrollbar behavior
You should consider using a Flickable instead of setting the position of your text manually:
Flickable {
anchors.fill: parent
contentWidth: content.paintedWidth
boundsBehavior: Flickable.StopAtBounds
ScrollBar.horizontal: ScrollBar {
hoverEnabled: true
active: true
policy: ScrollBar.AlwaysOn
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
background: Rectangle {
color: "black"
}
}
Rectangle {
id: frame
clip: true
anchors.fill: parent
color: "purple"
Text {
id: content
text: "ABCDE"
font.pixelSize: 160
}
}
}
Edit:
If you really need the ScrollBar to be attached to a Rectangle, you can add bounds to your Text position:
x: Math.min(0, Math.max(-hbar.position * width, frame.width - content.width))
with
ScrollBar {
visible: frame.width < content.width
// ...
}

Text becomes blurry when resizing window

I have a centered rectangle with a drop shadow behind it and some text within it.
import QtQuick 2.5
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0
Window {
visible: true
width: 800; height: 640
Rectangle{
id: centerRect
width: parent.width * 0.7; height: parent.height * 0.7
anchors{
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
radius: 7
border.color: "#C0C0C0"
Text{
text: "Hello World!"
font.pixelSize: 0.07 * parent.height
anchors{
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
}
}
DropShadow
{
anchors.fill: centerRect
horizontalOffset: 1; verticalOffset: 1
radius: 5
samples: 11
color: "#CDCDCD"
source: centerRect
}
}
When I resize the window the text becomes slightly blurred or out of focus. I thought it may have been an issue with how I'm scaling the font pixel size to the rectangle height but the problem is the same with static values. If I remove the drop shadow effect the text's visibility is fine when I resize the window.
How can I maintain good text visibility when using a drop shadow and resizing the window? I'm using Qt 5.5.1 on OpenSUSE Leap 42.1 (Plasma 5.5.5).
Solution 1: Use DropShadow only for the background rectangle and draw the text on top of that.
Solution 2: Use integral width and height for the centerRect. The graphical effect renders the centerRect first into a texture. If the source width or height are not integers, the texture size will not correspond to the original item size. When painting the texture, texture coordinates will not hit the pixel positions accurately and some interpolation is needed.
For me, the simplest is to move the Text out of centerRect, so it will not be its child obj, so not influced by the side effect of DropShadow.
eg:
move the text outside and modify its conditioning like below:
Text{
text: "Hello World!"
font.pixelSize: 0.07 * centerRect.height
anchors.centerIn: centerRect
}

QML (Qt 5): Overlay button on top left corner of resized image

I have this code (reduced to minimal):
import QtQuick 2.0
import QtQuick.Controls 1.3
Item {
Image {
id: img
source: "cluster.png"
width: 150
height: 150
fillMode: Image.PreserveAspectFit
}
Button {
id: butn
anchors.left: img.left
anchors.top: img.top
width: 20
height: 20
text: "Push!"
}
}
Which produces an image similar to the following:
However I would like to put the button at the top left of the resized image.
Full image at: http://susepaste.org/34762236
Is this possible with QML?
You need to access the actual size of the scaled image, in order to so there is the paintedHeight property and paintedWidth.
This would result in
Item {
Image {
id: img
source: "cluster.png"
width: 150
height: 150
fillMode: Image.PreserveAspectFit
}
Button {
id: butn
anchors.left: img.left
anchors.top: img.top
anchors.leftMargin: (img.width - img.paintedWidth)/2
anchors.topMargin: (img.height - img.paintedHeight)/2
width: 20
height: 20
text: "Push!"
}
}
You can alternatively use x or y instead of anchors and margins.

Resources