I'm developing a mobile app using App Studio for ArcGIS.
All my QML files has been set a fixed size and x,y axis according to my Xd files. But when I run it on my mobile and other mobiles - it does not support properly. I tried to find different solutions but I was not able to apply it on my page. Also, explored the scalability documentation of QML, but I was not able to understand it.
here is the sample code
App{
id:app
visible: true
x: 0
y: 0
width: 375
height: 812
Page{
anchors.fill: parent
background:
Image {
id: image
x: 0
y: 0
width: 375
height: 812
fillMode: Image.PreserveAspectFit
source: "images/login_backgroud.png"
}
Button {
id: button
x: 52
y: 674
width: 284
height: 40
text: qsTr("Login")
spacing: 0
font.pointSize: 16
}
}
}
Use anchors and layouts instead of hard coding x and y. Set attribute for enabling high DPI scaling. Refer to this Qt documentation for supporting GUI scalability in different form factors, resolutions and DPI.
https://doc.qt.io/qt-5/scalability.html
I'm developing a Qt5.11.1 QML application that runs into a QQuickWidget. The resize mode is set to SizeRootObjectToView. Hence, whenever I resize the QMainWindow I see my QML root object that scales too.
Inside I have some images anchored to fill the parent, and they are scaled as expected. Instead I have issues with smaller images or text that should maintain the same relative position and size.
I begin with absolute position and size when ratio is 1:1. Example: the root item has a size of 1920x1080 px, and I must place the other items (mainly images and texts) to given coordinates.
When the root changes its size all the elements should follow it. I tried this:
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtGraphicalEffects 1.0
Rectangle {
id: root
visible: true
color: "black"
property real ratio: root.width / 1920
readonly property real x_CenterGauge: 502
readonly property real y_CenterGauge: 489
Image {
x: x_CenterGauge * ratio
y: y_CenterGauge * ratio
scale: ratio
}
}
but this doesn't work because the root.width property (and in turn ratio) doesn't change when I resize the window. But it actually resize the root element because any anchored item will resize too! I get a change only if I maximize/minimize the window.
I read this article and this question, but I still don't understand how to handle the resising in QML.
In testing it is the property scale that seems to be a problem
By modifying width and height instead it solves the problem
Rectangle {
id: root
visible: true
color: "black"
property real ratio: root.width / 1920
readonly property real x_CenterGauge: 202
readonly property real y_CenterGauge: 489
Image {
x: root.x_CenterGauge * root.ratio
y: root.y_CenterGauge * root.ratio
width: implicitWidth * root.ratio
height: implicitHeight * root.ratio
//scale: ratio
}
}
I use Qt 5.10.1 on up-to-date Windows 10 and the following simple program does not show any window:
import QtQuick 2.10
import QtQuick.Window 2.10
import QtWebEngine 1.5
Window { id: w
visible: true
title: "Test"
// with this line, the program crashes before showing anything:
height: v.contentsSize.height
WebEngineView { id: v
anchors.left: w.left
anchors.right: w.right
anchors.top: w.top
onContentsSizeChanged: {
console.log(contentsSize) // no output if not both width and height properties of the web view are specified
w.height = contentsSize.height
}
// if any of the following 2 lines are omitted, the web view the ":-)" string in the web view does not show up and the window looks empty although anchors.left and anchors.right are set above and the height is set
// width: 100
// height: 100
// The following line crashes the program before showing the window
// height: v.contentsSize.height
Component.onCompleted: {
loadHtml(":-)");
}
}
}
I specifically want the window to be as high as the web view when its size is not constrained. Relevant documentation link: http://doc.qt.io/qt-5/qml-qtwebengine-webengineview.html#contentsSize-prop.
// with this line, the program crashes before showing anything:
height: v.contentsSize.height
That is because contentsSize is undefined at this point .. you haven't loaded any content yet, the qml engine crashes with undefined height. So just leave Window with no height .. equivalent to (height:0)
I specifically want the window to be as high as the web view when its
size is not constrained.
Then don't anchor the WebEngineView .. that's the problem, because your anchoring - which is not complete - will give WebEngineView an initial height following initial default height of Window, but you never change it later after loading .. so even Window will not be able to resize to a smaller height!
To do that safely with minimum change, set height/width of WebEngineView to any value initially .. then once the contents are loaded, reset WebEngineView height / width to contentsSize .. so thatWindow can resize to that height.
Window { id: w
visible: true
title: "Test"
WebEngineView {
id: v
width:1
height:1
onContentsSizeChanged: {
console.log(contentsSize) // no output if not both width and height properties of the web view are specified
//
// here you can set web view height so that Window heigth is same as webview
width = contentsSize.width
height = contentsSize.height
// and Window height
w.height = contentsSize.height
}
Component.onCompleted: {
loadHtml(":-)");
}
}
}
I am looking at the QML Style for the virtual keyboard. What is the purpose of keyboardDesignWidth and Height? I seem to have a lot of trouble managing the width and height of the keyboard and can never set it to how I want it. Setting the keyboardHeight and Width directly also does not help much.
The issue is that the component background size is somehow computed behind the scenes. So, even when I have the keyboard buttons and size how I want, the extraneous background covers some of my other control and it is very difficult to have a fine grained control over the size of the keyboard.
What is the right way to control the width and size of the virtual keyboard directly?
To Quote from the Documentation
The keyboard size is automatically calculated from the available width; that is, the keyboard maintains the aspect ratio specified by the current style. Therefore the application should only set the width and y coordinates of the InputPanel, and not the height.
So if you want to have a specific height, you need to set the width accordingly.
What is the right way to control the width and size of the virtual keyboard directly?
e.g.
InputPanel {
anchors.fill: parent
anchors.leftMargin: 100
anchors.rightMargin: 100
}
e.g.
InputPanel {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
width: 30
}
So what's the deal with the keyboardDesignHeight/Width? Well this seems to be the dimensions of the keyboard, when it is not necessary to scale it:
scaleHint : real
The keyboard style scale hint. This value is determined by dividing keyboardHeight by keyboardDesignHeight. All pixel dimensions must be proportional to this value.
This property is readonly!
So setting those will not disable the automatic resizing of your input panel in dependence of the width.
You might use them maybe, to calculate a ratio, and from this set the width to achieve your desired height.
Maybe this example helps you to understand this property:
import QtQuick 2.6
import QtQuick.Window 2.0
import QtQuick.Controls 2.0
import QtQuick.VirtualKeyboard 2.0
ApplicationWindow {
id:appwindow
visible: true
width: 800
height: 600
title: qsTr("Test")
InputPanel {
id: ip
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
width: 800
Component.onCompleted: console.log(Object.keys(ip.keyboard.style).sort())
}
Slider {
id: sl
from: 0
to: 3000
}
Binding {
target: ip.keyboard.style
property: 'keyboardDesignHeight'
value: sl.value
}
}
What is the difference between width/height and implicitWidth/Height in QML? When should one set the implicit dimensions instead of the regular? When should one ask the implicit dimensions instead of the regular from a component/item?
Generally, usage of implicitHeight/Width only makes sense within reusable components.
It gives a hint, of the natural size of the Item without enforcing this size.
Let's take a Image as an example. The natural size of the image would map one pixel from the image file to one pixel on the screen. But it allows us to stretch it, so the size is not enforced and can be overridden.
Let's say now, we want to have a gallery with pictures of unknown dimension, and we don't want to grow but only shrink them if necessary. So we need to store the natural size of the image. That is, where the implicit height comes into play.
Image {
width: Math.max(150, implicitWidth)
height: Math.max(150, implicitHeight)
}
In custom components, you have a choice on how to define the sizes.
The one choice is, to have all dimensions relative to the components root-node, maybe like this:
Item {
id: root
Rectangle {
width: root.width * 0.2
height: root.height * 0.2
color: 'red'
}
Rectangle {
x: 0.2 * root.width
y: 0.2 * root.height
width: root.width * 0.8
height: root.height * 0.8
color: 'green'
}
}
In this case, there is no natural size of the object. Everything works out perfectly for each size you set for the component.
On the other hand, you might have an object, that has a natural size - that happens, e.g. if you have absolute values in it
Item {
id: root
property alias model: repeater.model
Repeater {
id: repeater
delegate: Rectangle {
width: 100
height: 100
x: 102 * index
y: 102 * index
}
}
}
In this example you should provide the user with information about the natural size, where the content does not protude the item. The user might still decide to set a smaller size and deal with the protrusion, e.g. by clipping it, but he needs the information about the natural size to make his decision.
In many cases, childrenRect.height/width is a good measure for the implcitHeight/Width, but there are examples, where this is not a good idea. - e.g. when the content of the item has x: -500.
A real life example is the Flickable that is specifically designed to contain larger objects than its own size. Having the size of the Flickable to be equal to the content would not be natural.
Also be careful, when using scale in custom components, as the childrenRect will not know about the scaling.
Item {
id: root
implicitWidth: child.width * child.scale
implicitHeight: child.height * child.scale
Rectangle {
id: child
width: 100
height: 100
scale: 3
color: 'red'
}
}
And to your comment: I just don't understand why it is better to set implicitWidth/Height instead of setting width/height of a component's root dimension.
implicitWidht/Height are not a necessety - QtQuick could do without them. They exist for convenience and shall be convention.
Rule of Thumb
When you want to set dimension of a root node of a reusable component, set implicitWidth/Height.
In some cases, set it for non-root-nodes, if the nodes are exposed as a property.
Do so only, if you have a reason for it (many official components come without any).
When you use a component, set width/height.
I don't have the definitive answer but I can tell you what I found out. First, from the documentation:
implicitWidth : real
Defines the natural width or height of the Item if no width or height
is specified.
The default implicit size for most items is 0x0, however some items
have an inherent implicit size which cannot be overridden, for
example, Image and Text.
but less informative for width:
width
Defines the item's position and size.
The width and height reflect the actual size of the item in the scene. The implicit size is some kind of inherent property of the item itself.1
I use them as follows: When I create a new item and it can be resized, I set an implicit size inside the object2. When I'm using the object, I often set the real size explicitly from the outside.
The implicit size of an object can be overridden by setting height and width.
an example: TextWithBackground.qml
Item {
implicitWidth: text.implicitWidth
implicitHeight: text.implicitHeight
// the rectangle will expand to the real size of the item
Rectangle { anchors.fill: parent; color: "yellow" }
Text { id: text; text: "Lorem ipsum dolor..." }
}
an example: MyWindow.qml
Item {
width: 400
height: 300
TextWithBackground {
// half of the scene, but never smaller than its implicitWidth
width: Math.max(parent.width / 2, implicitWidth)
// the height of the element is equal to implicitHeight
// because height is not explicitly set
}
}
1) For some elements, like Text, the implicit height depends on the (not-implicit) width.
2) The implicit size usually depends on the implicit size of its children.
Implicit size is supposed to be used when calculating size of an item based on its contents. Whereas setting width or height on a parent item may affect the size of its children it should never be a case, when you set implicit size.
Rule of thumb
Implicit size should only "bubble up", i.e. children should never
lookup for implicit size of their parent to calculate their own
implicit size, neither parent should try to force implicit size of its
children.
If you would try to set width on a component similar to layout, that initially calculates its width from the width (rather than implicitWidth) of its child item and that child is affected by the size of a parent, you would end up with a binding loop.
This is why the property exists - to break cyclic dependencies when calculating size of an item based on its contents.