QML: set smooth painting - qt

While playing with QML I noticed a strange behavior. Let's say I have simple QML code:
Rectangle {
anchors.centerIn: parent
width:200
height:100
color:"yellow"
border.color: "green"
border.width: 10
rotation: 190
}
And the result:
The image looks poor, especially the border.
But if I add radius: 1 I get a very different picture:
Now it looks much better. the border also looks more smoother. Btw, setting smooth property do nothing. It looks that setting radius switches on some internal smoothing. So my question - how can I set this smooth without setting radius?
I use Qt 5.4 on Debian 7

The property you need to set is antialiasing. This is documented here:
antialiasing : bool
Used to decide if the Rectangle should use antialiasing or not.
Antialiasing provides information on the performance implications of
this property.
The default is true for Rectangles with a radius, and false otherwise.
(Emphasis mine.)

Related

QML/Qt: Make displayed text as large as possible depending on the parent containing it

I am trying to make a very simple KDE-Plasma Widget where only a certain number is displayed. I want to make this displayed number have a font size as large as possible depending on the parent containing it.
Here is what it looks right now:
As you can see, the text inside has a lot of space around it. What I actually want it to be is something like the "Date And Time" Widget found in KDE Plasma (my widget is right next to it for comparison):
Here, the time displayed has much lesser space around it while also auto-resizing whenever the panel height is changed.
Here is what the current code looks like:
import QtQuick 2.6
import QtQuick.Layouts 1.0
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.plasmoid 2.0
Item {
id: main
anchors.fill: parent
Layout.minimumWidth: units.iconSizes.large
Layout.minimumHeight: units.iconSizes.large
Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation
PlasmaComponents.Label {
id: display
anchors {
fill: parent
margins: Math.round(parent.width * 0.1)
}
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: foobar
font.pixelSize: 1000;
minimumPointSize: theme.smallestFont.pointSize
fontSizeMode: Text.Fit
font.bold: true
}
Timer {
some stuff
}
}
I tried looking into the code of the above Date and Time widget and wrote down the exact same layouts/controls (which is what you are seeing in the above code) with the same positioning/styling properties and yet I get a lot of space around my text/or the font size continues to remain small.
I tried your code and it resized the font correctly. For the spacing around the text, there are two points:
The spacing on the left and right is easily controlled by adjusting the margins value that you are using. For less space, try Math.round(parent.width * 0.05).
The spacing on the top and bottom is larger because the shape of your parent object is square, while the shape of the text is rectangular. In order to make the text fit the height of the square without exceeding the width of the square, the text would not just need to resize, it would need to be stretched vertically. But QML does not have an easy way to do that, and I doubt that's really what you want anyway.
EDIT:
And if you do want font stretching, I'll point you to this answer.
Thanks to #JarMan's input I was able to realize that my text was being rendered in small font because of lack of space due to the root (item) element being square in shape.
I have now figured that to change the layout sizes of the root element inside the KDE-Plasma panel, one needs to mess with Layout.preferredWidth and Layout.preferredHeight.
Here is what I did:
item {
.
.
Layout.preferredWidth: 150 * units.devicePixelRatio
Layout.preferredHeight: 50 * units.devicePixelRatio
.
.
}
Note: the 150 and 50 values aren't final. It basically gives an idea about the ratio at which the root element's width and height should be in (and I wanted a rectangle). It automatically resizes the inner content too as the Plasma Panel is resized.

SVG rasterization issue in a QML Canvas

I am experiencing issues when using the QML Canvas drawImage method to render SVG icons.
Basically the QML Canvas ignores the rasterization size and paint the image starting from its original size (in this case 48x48px), and scaling it up with an ugly aliasing effect.
Has anyone ever seen this and possibly figured out a solution ?
Please see QTBUG-59878 for a working self-contained example.
Here I'm gonna copy just the QML code and a screenshot of what I see.
From the left:
the original SVG icon as Image item (correct)
the same Image item rendered by drawImage (to be honest I expected this to be correct as well, since rasterized data should be provided by Image)
the SVG icon loaded with the procedure explained in the documentation, with loadImage and onImageLoaded
import QtQuick 2.0
Rectangle
{
width: 640
height: 480
Image
{
id: svgIcon
source: "qrc:/qt_logo.svg"
x: 10
y: 100
width: 180
height: 200
sourceSize: Qt.size(width, height)
}
Canvas
{
id: canvas
anchors.fill: parent
contextType: "2d"
property string imagefile: "qrc:/qt_logo.svg"
Component.onCompleted: context.loadImage(imagefile)
onImageLoaded: requestPaint()
onPaint:
{
context.drawImage(svgIcon, 200, 100, 180, 200)
context.drawImage(imagefile, 400, 100, 180, 200)
}
}
}
I have worked with SVG within QML, the performance is very poor and quality of upscaling and downscaling isn't good enough. if you're using SVG for showing icons, i will suggest you to use fonts instead of svg icons, its pretty fast and high quality. you can convert your svg icons to font characters, and pack them in single font and use it within QML as Text or label elements, seen Iconmoon.io

Binding expression + animation causes object to disappear and reappear randomly

I have a visual tree of the following object:
Row {
spacing: 4
y: 1
U_Icon {
width: 48
height: 48
scale: (activeo === main.object ? 1.18 : 1) * (main.expand ? 1 : 0.75)
Behavior on scale { SpringAnimation { spring: 10; damping: 0.2; duration: 100 } }
color: activeo == object ? "white" : "#262626"
anchors.verticalCenter: parent.verticalCenter
}
Column {
spacing: -10
Text {
text: object.type + "type"
font.pointSize: 10
font.family: sysfont
}
Text {
text: "name"
font.pointSize: 20
font.family: sysfont
font.italic: true
font.letterSpacing: -1
}
}
}
The scale of the icon depends on whether the current object is selected or expanded. Expanding causes the object to draw its children objects. However, on re-expanding after contracting, depending on the tree structure, children objects are missing their text, which mysteriously reappears when another object is selected or created. Selecting another object might cause one, several or all missing texts to appear, the same goes for creating another object. When the tree is expanded, the texts are there for an instant, after which they disappear.
I made a few observations:
if the binding for the scale is only either of the two expressions without the other, the problem does not manifest
if the animation is removed, the problem does not manifest
interfacing the icon scale as an alias property of the row in order to move the binding out of the component and to the place it is instantiated has no effect, the problem persist
breaking down the binding expression by adding dedicated activefactor and expandfactor property for each expression and reducing the scale binding to activefactor * expandfactor has no effect, the problem persists
refactoring the binding expression to a code block with a return statement (sometimes that helps when single liners fail) has no effect, the problem persists
Here is an illustration of what's going on:
1 - the tree builds OK
2 - the tree is collapsed
3 - the tree is expanded again, the text flashes for a moment and disappears
4 - clicking arbitrary object causes all text to reappear
Any ideas what's going on? Yet another bug or am I missing something? Why would a slightly more complex expression cause the column with the text to disappear? It is not a problem of the changing scale in particular, since both expressions change it and both work on their own.
Note that the text is still there, just not being rendered by the scene-graph, that is evident from the size of the light-grey rounded rectangle which is sized to match the row width. The scale of the icon itself is evaluated and displayed property, but for some reason causes the text to disappear.
EDIT: Another curious observation, if the text column is replaced by a common rectangle, the bug does not manifest. If the column is wrapped inside a rectangle the same width as the column, but only as high as the small text, this causes only the large text to go missing:
This adds more weight to my suspicion that this is a bug in the scene-graph, and wrapping it in a rectangle forces the renderer to update only that portion of the missing text. Note that the rectangle is not clipping the column. Furthermore, if the rectangle color is set to #00000000, that is fully transparent, the text is missing again, the scene graph disregards it, and thus there is nothing to force the update of the text part. As expected, wrapping in an Item is no help either, nor is using text directly, without the column. If the rectangle is extended further down, it cuts through the big text, as a result, only the upper half of the big text is visible. Even the tiniest amount of transparency in the rectangle causes the text to go missing, even if the rectangle is 99.99% opaque. Only a 100% opaque rectangle forces the visibility of the text.
I have tested it with latest Qt 5.7 on windows 7 x64 (stock x86 qt build + custom x64 opengl static) and linux x64 (using the mesa drivers).

How to make svg icons crisp again in Qt 5.6 on high DPI screens

Upgrading from Qt 5.4 to Qt 5.6 made all my .svg icons blurry/pixelated. I noticed this happens only on high density screens like on my MacBookPro Retina Display. I read the documentation of High DPI support in Qt 5.6 and I have set the QT_AUTO_SCREEN_SCALE_FACTOR=1 environment variable, but it didn't have much effect. Anybody has this issue? I have also found this bug report which probably relates to my question.
EDIT 1:
A simple example would be:
Image {
source: my_icon.svg
sourceSize.width: 50
sourceSize.height: 50
anchor.centerIn: parent
}
This is an ugly hack, but it did the trick:
Item {
property alias image: mySvgImage
implicitWidth: mySvgImage.paintedWidth
implicitHeight: mySvgImage.implicitHeight / Screen.devicePixelRatio
Image {
id: mySvgImage
sourceSize.width: width * Screen.devicePixelRatio
sourceSize.height: height * Screen.devicePixelRatio
}
}
I'm not sure how to apply this in QML, but you need to set the attribute AA_UseHighDpiPixmaps with QWidgets. Might well be the same with QML. E.g:
app.setAttribute(Qt.AA_UseHighDpiPixmaps)

QML Minimum drag/flick distance for changing item

I have a ListView in QML using theese properties :
ListView {
id : list
boundsBehaviour: Flickable.StopAtBounds
snapMode: PathView.SnapOneItem
highlightFollowsCurrentItem: true
highlightRangeMode: ListView.StrictlyEnforceRange
...
}
My problem is the following :
I'm trying to determine exactly when the drag/flick will made the list move to the next/previous item or staying on the same one when releasing the touch.
Is there a property to modify or something useful to know which behaviour will happen ?
Thanks.
you are looking for startDragDistance property in QApplication class, the default value of startDragDistance is 10 pixels for Windows (it depends on OS)
In order to set drag distance to 50 pixels, you can use the following line
QApplication::setStartDragDistance(50);

Resources