I want to achieve some kind of inheritance, like - I have base frame, and then modify it. Here is code sample.
BaseFrame.qml:
Rectangle {
id: base
anchors.fill: parent
function setButtonY (y) {
console.log("Down to ", y)
requestButton.y = y
}
Button {
id: requestButton
width: 200
x: (parent.width / 2) - 100
y: 100
}
}
DerivedFrame.qml:
BaseFrame{
anchors.fill: parent
onVisibleChanged: {
setButtonY(300)
}
Button{
x: 100
y: 100
width: 200
height: 200
visible: true
}
}
The problem is, when I use DerivedFrame - only BaseFrame is shown. If I add some buttons like below, they are never shown:
DerivedFrame {
Button {
// some stuff here + visible: true
}
}
Also - setButtonY correctly show log with correct y, but requestButton never move to the required y. Is there a way to achieve this?
Using absolute positioning is not advised. You can exploit a positioning type (e.g. Column) to automatically lay out your items. However you have to ensure that, while added to BaseFrame.qml, Items are correctly inserted in the positioning item.
When Items are added to a parent, they are inserted inside the default property. In each Item-derived type, data property is the default one. Then we alias the data of the positioning Item and then make that alias the default property. This way we obtain the result searched in the previous paragraph. The BaseFrame.qml could look like this:
import QtQuick 2.0
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
Item {
id: base
anchors.fill: parent
default property alias hook: rowContainer.data //aliasing
Column {
id: rowContainer
anchors.fill: parent
Button {
id: requestButton
width: 300
height: 100
text: "1"
}
}
}
This is a DerivedFrame.qml possible implementation:
import QtQuick 2.0
import QtQuick.Controls 1.2
BaseFrame{
anchors.fill: parent
Button{
anchors.right: parent.right
width: 200
height: 200
text: "2"
}
}
And finally here is the main.qml code:
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls 1.2
ApplicationWindow {
visible: true
width: 500
height: 500
DerivedFrame {
Button {
anchors.horizontalCenter: parent.horizontalCenter
text: "3"
}
}
}
Obviously this is just one of the possible ways to create a dynamic type. You can also have a look to this video, whereas this answer deals with dynamic addition. Finally this answer provides another example usage of default alias.
Related
I am using Qt 5.15 Quick 2 QML to create a row of custom buttons in a window. When I have a standalone custom button things appear to work fine, but when I put them in a RowLayout there appears to be severe clipping and artifacting issues.
A minimum reproducible example might look like:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
RowLayout
{
anchors.fill:parent
anchors.margins: 25
Button
{
text: "Click Me"
Layout.fillWidth: true
}
CustomButton
{
text: "That Boy Don't Glow Right"
}
Button
{
x: 100; y:100
text: "Click Me"
Layout.fillWidth: true
}
}
}
with the custom control
import QtQuick 2.0
import QtQuick.Controls 2.15
import QtGraphicalEffects 1.15
Button {
id: control
text: "Click Me"
Glow {
anchors.fill: control
radius: 64
spread: 0
samples: 128
color: "red"
source: control
visible: true
}
}
with example output:
One potential fix is to add change the Glow to
Glow {
anchors.fill: control
width: parent.width
height:parent.height
x:control.x
y:control.y
parent: control.parent
...
But this doesn't seem right. First, it's not obvious to me where parent.width and control.x and control.parent are bound from and what happens in single and multiple nesting. If a CustomButton is placed inside another control with id control, would it rebind the property? And it appears if a RowLayout is placed inside a RowLayout, then it would require parent: control.parent.parent. In my actual code there is some non-trivial positioning to allow margins for a drop shadow, too, and the CustomButton is in another container so the actual code that works is: x:control.x + parent.pad/2 and parent:control.parent.parent.parent which is, frankly, ridiculous and assumes that non-standard fields in the parent are always available.
Is there a better way? Was hoping I could keep the button's ability to glow itself.
According to the docs:
"Note: It is not supported to let the effect include itself, for instance by setting source to the effect's parent."
So it's fortunate that you were able to get your example to work at all. One way to avoid using the parent as a source is to point the Glow object at the Button's background object:
Button {
id: control
Glow {
source: control.background
}
}
Can anyone tell me why the following fails?
The Rectangles specify border.width: top.bw where bw is a property in the top Window which has id:top. But the result is zero.
If I replace top.bw with just bw it works in this demo but not in the real application which might have a bw defined in an intermediate object. So I need to specify top.bw somehow.
What's wong with this?
import QtQuick 2.14
import QtQuick.Window 2.14
Window {
id: top
width:800; height: 800
property double bw: 15
ListView {
anchors.fill:parent
model: 3
delegate: Rectangle {
width: 100; height: 100
border.width: top.bw
}
}
}
To understand the problem you must add the following:
Component.onCompleted: console.log(top)
And you will get the following:
qml: QVariant(QQuickAnchorLine, )
So it appears that "top" is an undocumented property in Item(This property is for the use of anchors, for more information read Positioning with Anchors) causing a variable name conflict. The solution is to use another id like "root".
import QtQuick 2.14
import QtQuick.Window 2.14
Window {
id: root
width:800; height: 800
property double bw: 15
ListView {
anchors.fill:parent
model: 3
delegate: Rectangle {
width: 100; height: 100
border.width: root.bw
}
}
}
I need to create components dynamically add added to an area of the screen that, of course, needs to be scrollable. I found out that no matter how many of components I added with the scroll bar as its parent, the scroll bars would not appear and the element would not be scrollable.
I did a little fiddling and I think I came up with a minum working example of what I am talking about:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ScrollView {
width: 200
height: 200
clip: true
Label {
text: "ABC"
font.pixelSize: 224
}
// Rectangle {
// color: "#ff0000"
// width: 100
// height: 100
// }
}
}
This is a modified version of the example used int he official documentation. However when I uncomment the square the screen is no longer scrollable (scroll bars never appear).
If I remove the label and leave the rectangle (making it larger so that there is something to scroll to) it still doesn't work.
I am using Qt 5.10.
So the code below worked for me. I defined a rectangle as a backgroud to get border lines to a scrollable table that I need to create.
Rectangle {
id: tableBackground
color: "#ffffff"
border.width: 2
border.color: "#EDEDEE"
radius: 4
anchors.top: tableHeader.bottom
anchors.left: tableHeader.left
width: vmTableWidth
height: vmTableHeight - tableHeader.height
ScrollView {
id: tableArea
anchors.fill: parent
clip: true
ListView {
id: patientListView
anchors.fill: parent
model: patientList
delegate: VMPatientEntry {
onFetchReport: {
// This is a signal emitted by my VMPatientEntry.
}
}
onCurrentIndexChanged: {
// Do stuff when the current index changes.
}
}
}
}
So I hope this answer allows someone to fix their problem as well.
Quick Controls 2, Qt 5.10.
I created table control based on ListView item.
One of its columns is displayed using this component:
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
Item
{
id: root
implicitHeight: item1.implicitHeight
ColumnLayout
{
id: item1
visible: !model.finished
width: parent.width
RowLayout
{
Label
{
text: "38%"
Layout.alignment: Qt.AlignLeft
}
Label
{
text: "Paused"
Layout.alignment: Qt.AlignRight
}
}
ProgressBar
{
from: 0; to: 100; value: 40
// Variant A
/*Layout.preferredWidth: 30
Layout.preferredHeight: 10*/
// Variant B
width: 30
height: 10
}
}
}
Can somebody please explain me why Variant B does not "work". I may specify any width/height values or even just remove them - no effect. Variant A (Layout.preferredWidth/Layout.preferredHeight) works fine.
Variant A:
Variant B:
The ...Layout items alter the dimensions of their children. That is their purpose, and the behavior is documented.
As per documentation of the ColumnLayout Layout.preferredWidth the behavior is:
This property holds the preferred width of an item in a layout. If the preferred width is -1 it will be ignored, and the layout will use implicitWidth instead. The default is -1.
Since the default is -1, it will take the implicitWidth - it is not written "and use width instead".
If you don't want to use Layout don't use Layout. You can just take Column instead.
I have ListView with my own delegate.
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ItemDelegate
{
height: 40
Row
{
spacing: 10
anchors.verticalCenter: parent.verticalCenter
CheckBox
{
}
}
}
The problem is that check boxes does not resize despite ItemDelegate's height.
I get this for height = 40:
I get this for height = 10:
I've tried playing with CheckBox'es width and height values - did not help.
Is it possible to make it smaller at all, without customizing it?
You can, in theory, increase the size of the indicator, but it won't increase the size of the checkmark image:
CheckBox {
text: "CheckBox"
anchors.centerIn: parent
checked: true
indicator.width: 64
indicator.height: 64
}
There are a couple of reasons why the image is not scaled. First of all, the checkmark would be blurry if it was upscaled. And more importantly, to retain best possible performance. Instead of calculating all the sizes relative to each other and that way creating huge amounts of bindings like Qt Quick Controls 1 did, Qt Quick Controls 2 bases its scalability instead on the automatic high-DPI scaling system introduced in Qt 5.6. You get simply a different #Nx image when running with scale factor N.
I'm afraid you need to customize your checkbox to get a different size.
Example:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQml 2.2
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Component {
id: contactDelegate
ItemDelegate
{
id: item
width: 40
height: 40
CheckBox
{
id: control
text: name
indicator: Rectangle {
implicitWidth: item.width
implicitHeight: item.height
x: control.leftPadding
y: parent.height / 2 - height / 2
border.color: control.down ? "#dark" : "#grey"
Rectangle {
width: 25
height: 25
x: 7
y: 7
color: control.down ? "#dark" : "#grey"
visible: control.checked
}
}
}
}
}
ListView {
width: 180;
height: 200;
spacing: 10
model: ContactModel {}
delegate: contactDelegate
}
}
By the way, the spacing property should be set in your ListView, not the delegate. Otherwise, it has no effect.