How to center all column items in QML - qt

I have this QML code, but I need to center horizontally Text and Rectangle, how can I do it? Can it be done somehow except settimg horizontal alignment for both of them< can I write some dtyle that will be applied to all children of column element?
Can I also set some styles to Column that will make automatical vertical spaces between my elements?
I want to make effect same to following css
.col{
dissplay:flex;
justify-content: space-around;
align-items: center;
}
And here id my QML code:
import QtQuick 2.3
import QtQuick.Window 2.1
import QtQuick.Layouts 1.15
Window {
// visible:true
ColumnLayout{
Layout.alignment:Qt.AlignHCenter
Text{
text:"CONTROL\n MANAGEMENT\n SYSTEM"
color:"#999999"
horizontalAlignment: Text.AlignHCenter
width:parent.width
}
Rectangle{
width:100
height:100
color:"#ff0000"
}
}
}

i found this working solution
import QtQuick 2.3
import QtQuick.Window 2.1
import QtQuick.Layouts 1.15
Window {
visible:true
Item{
// anchors.horizontalCenter: parent.horizontalCenter;
x:(parent.width-this.childrenRect.width)/2
ColumnLayout{
Text{
Layout.alignment:Qt.AlignHCenter
text:"CONTROL\n MANAGEMENT\n SYSTEM"
color:"#999999"
horizontalAlignment: Text.AlignHCenter
width:parent.width
}
Rectangle{
Layout.alignment:Qt.AlignHCenter
width:300
height:100
color:"#ff0000"
}
Rectangle{
Layout.alignment:Qt.AlignHCenter
width:200
height:100
color:"#ff0000"
}
}
}
}
But I still have a question if I can use some another methods, I do not want to write Layout.alignment:Qt.AlignHCenter in every child element.

Related

Why does my Custom QML Tooltip have no background?

I have created a custom tooltip style using this guide: https://doc.qt.io/qt-6/qtquickcontrols2-customize.html#creating-a-custom-style
here is ToolTip.qml within my style:
import QtQuick.Templates 2.0 as T
import QtQuick
T.ToolTip {
id: ctrl
contentItem: Text{
color: "red"
text: ctrl.text
}
background: Rectangle {
color: "blue"
border.color: "yellow"
}
}
And here is how I use it:
import QtQuick.Controls 2.15
import QtQml 2.15
import QtQuick.Layouts 2.15
import QtQuick
ApplicationWindow {
id: mainWindow
visible: true
width: 800
height: 600
visibility: Window.Maximized
Button {
anchors.centerIn: parent
id: button
text: "Click me"
onClicked: {
console.log("Clicked")
}
ToolTip.visible: hovered
ToolTip.text: "hello world"
}
}
The text colour works, but the background doesn't.
Why does it not show the blue background rectangle?
I am using Qt6 with PySide6.
*edit:
I have tried using TextMetrics to give the background a width and height. Is this the idiomatic way to do it? It feels like I shouldn't need text metrics. This also leaves the Label uncentered in the background, which looks bad.
import QtQuick.Templates 2.0 as T
import QtQuick
import QtQuick.Controls
T.ToolTip {
id: ctrl
contentItem: Label {
color: "red"
text: ctrl.text
}
background: Rectangle {
id: bg
color: "yellow"
width: tmet.width + 5
height: tmet.height + 5
}
TextMetrics {
id: tmet
font: ctrl.font
text: ctrl.text
}
}
Everytime I need to create custom controls I'll look into the QtQuick Basic style. On my machine I can find it here Qt/6.4.0/gcc_64/qml/QtQuick/Controls/Basic/ToolTip.qml
Templates are non-visual implementations of controls' logic and
behavior.
You need to set a size on the ToolTip. Look how they are setting the implicitWidth and implicitHeight of the ToolTip.
import QtQuick
import QtQuick.Controls.impl
import QtQuick.Templates as T
T.ToolTip {
id: control
x: parent ? (parent.width - implicitWidth) / 2 : 0
y: -implicitHeight - 3
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
contentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
contentHeight + topPadding + bottomPadding)
margins: 6
padding: 6
closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent | T.Popup.CloseOnReleaseOutsideParent
contentItem: Text {
text: control.text
font: control.font
wrapMode: Text.Wrap
color: control.palette.toolTipText
}
background: Rectangle {
border.color: control.palette.dark
color: control.palette.toolTipBase
}
}
To set the toolTip text color, it is not necessary to define a custom contentItem Label component. You can change the tooltip color by setting palette.toolTipText.
I can see your use case is to try to apply a custom ToolTip style so that all your components will inherit.
[EDIT: Change the direction of my answer to a custom Button instead of changing the default ToolTip style]
Alternatively, consider implementing custom components that have a custom ToolTip style. e.g. instead of Button, consider having MyButton. This way, we leave the default Button with the default style.
import QtQuick
import QtQuick.Controls
Page {
MyButton {
anchors.centerIn: parent
id: button
text: "Click me"
onClicked: {
console.log("Clicked")
}
ToolTip.visible: hovered
ToolTip.text: "hello world"
}
}
// MyButton.qml
import QtQuick
import QtQuick.Controls
Button {
ToolTip {
visible: parent.hovered
text: parent.ToolTip.text
palette.toolTipText: "red"
background: Rectangle {
color: "lightsteelblue"
border.color: "yellow"
}
}
}
You can Try it Online!

QML can't anchor to item in layout

Observe this quick example:
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.2
ApplicationWindow {
visible: true
width: 100
height: 100
Label {
text: "foobar"
anchors.bottom: row.top
anchors.left: label1.right
}
RowLayout {
id: row
anchors.bottom: parent.bottom
width: parent.width
Label {
id: label1
text: "hello1"
Layout.alignment: Qt.AlignLeft
}
Label {
id: label2
text: "hello2"
Layout.alignment: Qt.AlignRight
}
}
}
I have two items in row layout, and I want to anchor the third label to one of them. This is what i get:
I expect foobar to be more to the right, but it's not what I get.
Also with this any margins I set to the label will be ignored too.
I can anchor to window or to RowLayout and it would work nicely, but for some reason I can't anchor to items inside the layout. What's the reason and what's the appropriate solution for this?
When you compile the program you will get the error: Cannot anchor to an item that isn't a parent or sibling. Here's an answer, why you can't anchor. My solution in, that we will anchor to the left of row and then make margin with width of the label1 inside the row.
Here's a screenshot.
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.2
ApplicationWindow {
visible: true
width: 100
height: 100
Label {
color: "#b7087d"
text: "foobar"
anchors.bottom: row.top
anchors.left: row.left
anchors.leftMargin: label1.width
}
RowLayout {
id: row
anchors.bottom: parent.bottom
width: parent.width
Label {
id: label1
color: "#b22424"
text: "hello1"
Layout.alignment: Qt.AlignLeft
}
Label {
id: label2
color: "#1e62ce"
text: "hello2"
Layout.alignment: Qt.AlignRight
}
}
}

Extra space at the bottom of Flow

I have a QML code like this:
MyItem.qml:
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
Item {
id: root
width: parent.width
height: grid.height
Rectangle {
anchors.fill: root
color: "blue"
z: -1
}
Flow {
id: grid
width: parent.width
spacing: 5
Button {
text: qsTr("Button 1")
}
Button {
text: qsTr("Button 2")
}
Button {
text: qsTr("Button 3")
}
}
}
main.qml:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ColumnLayout {
anchors.fill: parent
Button {
Layout.fillWidth: true
Layout.fillHeight: true
text: "hello"
}
MyItem {
Layout.fillWidth: true
}
}
}
If the Flow is wide enough for all three buttons to be at the same line (as with RowLayout) there is an extra empty space at the bottom of the Flow (approximately Button.height * 2). Looks like the Flow height is always calculated as the sum of all its element heights.
What is the logic behind this behavior? How to make the Flow fit its content height?
EDIT1: It is not Flow, but 'root' item has the wrong height.
EDIT2: Download the sample app
The problem with your code is that the root element the expressions:
anchors.fill: parent
height: grid.height
are competing, in the first expression you indicate that the dimensions of the root will take the size of the window and this implies the height but in the next expression you are indicating that the height will no longer be from the window but from the grid, so that generates an indefinite behavior. The only solution is to establish that the width of the root item is that of the window.
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Item {
id: root
height: grid.height
width: parent.width
Rectangle {
anchors.fill: root
color: "blue"
}
Flow {
id: grid
width: parent.width
spacing: 5
Button {
text: qsTr("Button 1")
}
Button {
text: qsTr("Button 2")
}
Button {
text: qsTr("Button 3")
}
}
}
}
Update:
It seems that you do not know how they work (read https://doc.qt.io/qt-5/qml-qtquick-layouts-layout.html#details), by default the height that is taken is the implicitHeight.
Also if you use layout you should not set anchors in the items that are directly affected by the layouts, in your case the CommandsTab is affected by the Layout so you should not use width: parent.width, is unnecesary.
CommandsTab.qml
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
Item {
id: root
implicitHeight: grid.height
Rectangle {
anchors.fill: root
color: "blue"
z: -1
}
Flow {
id: grid
width: parent.width
spacing: 5
Button {
text: qsTr("Button 1")
}
Button {
text: qsTr("Button 2")
}
Button {
text: qsTr("Button 3")
}
}
}
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ColumnLayout {
anchors.fill: parent
Button {
Layout.fillWidth: true
Layout.fillHeight: true
text: "hello"
}
CommandsTab {
Layout.fillWidth: true
}
}
}

Applying mask to image breaks alignment

Whenever I apply a mask to an image to make it circular, the alignment of UI elements breaks. The image is offset to the right by some number of pixels.
// main.qml
import QtQuick 2.8
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.1
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Example")
Page1Form {
}
}
// Page1Form.qml
import QtQuick 2.8
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.1
Item {
RowLayout {
id: playerRowLayout
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
RoundedImage {
id: displayImage
width: 50
height: 50
Layout.preferredWidth: 50
Layout.preferredHeight: 50
source: "Images/DisplayPicture.jpeg"
sourceSize.width: width
sourceSize.height: height
}
Text {
id: playerText
text: qsTr("Hameer Abbasi (Pro)")
font.family: "Source Sans Pro"
font.pixelSize: 12
}
}
}
// RoundedImage.qml
import QtQuick 2.8
import QtGraphicalEffects 1.0
Image {
id: img
property bool rounded: true
property bool adapt: true
layer.enabled: rounded
layer.effect: OpacityMask {
maskSource: Rectangle {
anchors.centerIn: parent
width: adapt ? img.width : Math.min(img.width, img.height)
height: adapt ? img.height : Math.min(img.width, img.height)
radius: Math.min(width, height)*0.5
}
}
}
When I change RoundedImage to Image, the misalignment disappears, like so:
Also, when I add anchors.fill: img or anchors.centerIn: img to the OpacityMask, I get the following result (as you can see, the misalignment has not disappeared but just moved):
The only thing that does seem to work is setting the anchors.right: displayImage.left on the textbox, but that somehow seems like a hack and I feel like I'm not doing something right somehow. Can someone help me figure out where the issue is and what the "proper" way to fix this would be?
I can't explain you why this thing is happening. To me it looks like a bug.
Seemingly there is an easy workaround: Don't have the Image directly inside the Layout. Change the RoundedImage.qml to this:
// RoundedImage.qml
import QtQuick 2.7
import QtGraphicalEffects 1.0
Item {
id: img
property bool rounded: true
property bool adapt: true
property alias source: image.source
property alias sourceSize: image.sourceSize
Image {
id: image
width: img.width
height: img.height
layer.enabled: rounded
layer.effect: OpacityMask {
maskSource: Rectangle {
width: adapt ? img.width : Math.min(img.width, img.height)
height: adapt ? img.height : Math.min(img.width, img.height)
radius: Math.min(width, height)*0.5
}
}
}
}
and the strange behavior is gone.

TextAreaStyle cannot be assigned to style property

I have a problem using the style property to change the text color of a scrollable TextArea.
I also added the included modules from the .pro file:
QT += qml quick core quickcontrols2
This is what my .qml file looks like:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.1
import QtQuick.Controls.Material 2.0
import QtGraphicalEffects 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Test")
Page {
width: parent.width
height: parent.height
background: Rectangle {
color: "#000000"
width: parent.width
height: parent.height
}
Flickable {
id: flickable
anchors.bottom: parent.bottom
width: parent.width-50
flickableDirection: Flickable.VerticalFlick
height: 200
TextArea.flickable: TextArea {
id: pane1
text: "This is some text"
font.bold: false
font.pointSize: 10
wrapMode: Text.WordWrap
clip: true
style: TextAreaStyle {
textColor: "#4F4F4F"
}
background: Rectangle {
color: "#FFFFFF"
width: parent.width
height: parent.height
}
}
ScrollBar.vertical: ScrollBar { }
}
}
}
The Error message I get when running this example:
QQmlApplicationEngine failed to load component
qrc:/main.qml:38 Cannot assign to non-existent property "style"
I guess I am missing some dependency, but couldn't find anything in the documentation pointing me into the right direction.
Posting #BaCaRoZzo's comment as a community answer.
style property is not available in controls 2. Styling is inlined in the control. See here.
You can also remove import QtQuick.Controls.Styles 1.4 since it is necessary to styling controls 1.x, which you didn't import.

Resources