How to align the radio button text to the vertically center in QML - qml

I am new to Qt-QML.
I am trying to implement the radio buttons based on the size of the parent window and text to be aligned vertically center
But, the text beside radio buttons is not aligning vertically center.
Could you please help me where I am doing wrong?
Window {
id: mainwindow
visible: true
width: 640
height: 480
title: qsTr("Hello World")
function getActualValue( percent , value)
{
var percentageValue = Math.round((percent*value)/100);
return percentageValue;
}
GroupBox {
id: groupboxId
title: qsTr("Log Meas")
font.pixelSize: mainwindow.getActualValue(2, mainwindow.width)
width: mainwindow.width/4
height: mainwindow.height/8
anchors.centerIn: parent
RowLayout {
RadioButton {
id: radioButton1
checked: true
font.pixelSize: mainwindow.getActualValue(2, mainwindow.width)
text: qsTr("Imperial")
indicator: Rectangle {
implicitWidth: mainwindow.getActualValue(3, mainwindow.height)
implicitHeight: mainwindow.getActualValue(3, mainwindow.height)
radius: 9
border.color: radioButton1.activeFocus ? "red" : "gray"
border.width: 1
Rectangle {
anchors.fill: parent
visible: radioButton1.checked
color: "#555"
radius: 9
anchors.margins: 4
}
}
contentItem: Text {
text: radioButton1.text
font: radioButton1.font
opacity: enabled ? 1.0 : 0.3
color: radioButton1.down ? "#17a81a" : "#21be2b"
verticalAlignment: Text.AlignVCenter
leftPadding: radioButton1.indicator.width + radioButton1.spacing
}
}
RadioButton {
id: radioButton2
checked: false
font.pixelSize: mainwindow.getActualValue(2, mainwindow.width)
text: qsTr("Metric")
indicator: Rectangle {
implicitWidth: mainwindow.getActualValue(3, mainwindow.height)
implicitHeight: mainwindow.getActualValue(3, mainwindow.height)
radius: 9
border.color: radioButton2.activeFocus ? "darkblue" : "gray"
border.width: 1
Rectangle {
anchors.fill: parent
visible: radioButton2.checked
color: "#555"
radius: 9
anchors.margins: 4
}
}
contentItem: Text {
text: radioButton2.text
font: radioButton2.font
opacity: enabled ? 1.0 : 0.3
color: radioButton2.down ? "#17a81a" : "#21be2b"
verticalAlignment: Text.AlignVCenter
leftPadding: radioButton2.indicator.width + radioButton2.spacing
}
}
}
}
}
The output looks like below.
enter image description here

Working code is below. The biggest issue is that the text was indeed vertically centered. It's the indicator that was not.
Note, customizing controls is normally best done in fixed units of pixels and most of them assume that. If you really want dynamic scalability of controls you need to make sure everything (including all of the implicit sizes, paddings, spacings, etc.) are scaling appropriately.
Reviewing the base implementation here can help you with that:
https://github.com/qt/qtdeclarative/blob/dev/src/quickcontrols2/basic/RadioButton.qml
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
import QtQuick.Layouts 1.15
Window {
id: mainwindow
visible: true
width: 640
height: 480
title: qsTr("Hello World")
function getActualValue( percent , value)
{
var percentageValue = Math.round((percent*value)/100);
return percentageValue;
}
GroupBox {
id: groupboxId
title: qsTr("Log Meas")
font.pixelSize: mainwindow.getActualValue(2, mainwindow.width)
width: mainwindow.width/4
height: mainwindow.height/8
anchors.centerIn: parent
RowLayout {
RadioButton {
id: radioButton1
checked: true
font.pixelSize: mainwindow.getActualValue(2, mainwindow.width)
text: qsTr("Imperial")
implicitWidth: contentItem.contentWidth + indicator.width + 2 * spacing
implicitHeight: indicator.implicitHeight
indicator: Rectangle {
anchors.verticalCenter: parent.verticalCenter
implicitWidth: mainwindow.getActualValue(3, mainwindow.height)
implicitHeight: mainwindow.getActualValue(3, mainwindow.height)
radius: 9
border.color: radioButton1.activeFocus ? "red" : "gray"
border.width: 1
Rectangle {
anchors.fill: parent
visible: radioButton1.checked
color: "#555"
radius: 9
anchors.margins: 4
}
}
contentItem: Text {
text: radioButton1.text
font: radioButton1.font
opacity: enabled ? 1.0 : 0.3
color: radioButton1.down ? "#17a81a" : "#21be2b"
verticalAlignment: Text.AlignVCenter
leftPadding: radioButton1.indicator.width + radioButton1.spacing
}
}
RadioButton {
id: radioButton2
checked: false
font.pixelSize: mainwindow.getActualValue(2, mainwindow.width)
text: qsTr("Metric")
implicitWidth: contentItem.contentWidth + indicator.width + 2 * spacing
implicitHeight: indicator.implicitHeight
indicator: Rectangle {
anchors.verticalCenter: parent.verticalCenter
implicitWidth: mainwindow.getActualValue(3, mainwindow.height)
implicitHeight: mainwindow.getActualValue(3, mainwindow.height)
radius: 9
border.color: radioButton2.activeFocus ? "darkblue" : "gray"
border.width: 1
Rectangle {
anchors.fill: parent
visible: radioButton2.checked
color: "#555"
radius: 9
anchors.margins: 4
}
}
contentItem: Text {
text: radioButton2.text
font: radioButton2.font
opacity: enabled ? 1.0 : 0.3
color: radioButton2.down ? "#17a81a" : "#21be2b"
verticalAlignment: Text.AlignVCenter
leftPadding: radioButton2.indicator.width + radioButton2.spacing
}
}
}
}
}

Related

QML ListView delegate with Component Row does't render correctly

And now I have a problem with my qml script. here's the simple code:
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
id: root
anchors.fill: parent
color: "green"
SystemPalette { id: activePalette }
ColumnLayout {
id: rightPanel
Layout.fillHeight: true
Layout.fillWidth: true
Layout.rightMargin: 10
anchors.fill: parent
Component.onCompleted: {
console.log(this, width, parent, parent.width)
}
ListView {
spacing: 2
Layout.fillHeight: true
Layout.fillWidth: true
model: ListModel {
ListElement {
name: "nihao"
value: "1"
}
ListElement {
name: "fds"
value: "2"
}
ListElement {
name: "fdssd"
value: "4"
}
}
delegate: Component {
// Rectangle {
// color: "yellow"
// height: 40
// width: parent.width
Row {
anchors.fill: parent
spacing: 2
height: 40
width: 200
Rectangle {
color: activePalette.window
height: 25
width: 100
border.color: "white"
border.width: 3
Text {
anchors.centerIn: parent
text: name
}
}
Rectangle {
color: activePalette.window
height: 25
width: 100
border.color: "white"
border.width: 3
Text {
anchors.centerIn: parent
text: value
}
}
}
//}
}
}
}
}
}
The code does't display correctly when I use qmlscene to render it, it even render nothing if the ListModel is too long.
But, if I uncomment out the "Rectangle" code in delegate component, it works well. So I'm comfused with the difference between Reactangle and Row for that they are all inherited from Item. And what should be placed into the delegate component as its direct child?

Positioning text a center of Layout

I am working on some software using Qt 5.7 and I have simple Rectangle containing custom Button and Text:
import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtQuick.Window 2.3
Window
{
width: 1024
height: 768
visible: true
Rectangle
{
anchors.fill: parent
color: "#e4e4e4"
border.width: 0
border.color: "#e4e4e4"
radius: 32
ColumnLayout
{
anchors.fill: parent
spacing: 8
RowLayout
{
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: parent.height/2
Layout.preferredHeight: parent.height/2
Layout.maximumHeight: parent.height/2
Rectangle
{
id: buttonBack
property bool isPressed: false
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
Layout.minimumWidth: 128
Layout.preferredWidth: 128
Layout.maximumWidth: 128
Layout.minimumHeight: 128
Layout.preferredHeight: 128
Layout.maximumHeight: 128
color: "transparent"
Image
{
anchors.centerIn: parent
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
fillMode: Image.PreserveAspectFit
sourceSize.width: 128
sourceSize.height: 128
smooth: true
antialiasing: true
source: (buttonBack.isPressed===true)?"http://icons.iconarchive.com/icons/iconarchive/red-orb-alphabet/256/Letter-A-icon.png"
:"http://www.iconarchive.com/download/i14559/iconarchive/red-orb-alphabet/Arrow.ico"
} // Image
MouseArea
{
anchors.fill: parent
onPressed:
{
buttonBack.isPressed=true;
} // onPressed
onPressAndHold:
{
} // onPressAndHold
onReleased:
{
buttonBack.isPressed=false;
} // onReleased
onClicked:
{
} // onClicked
} // MouseArea
} // Rectangle
Text
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: "black"
text: qsTr("TEST TEXT")
font.pointSize: 24
} // Text
} // RowLayout
} // RowLayout
} // Rectangle
} // Window
The problems is the text "Test Text" is not horizontally aligned at center of screen becuase it has neighbour (button). How do I center this text horizontally regardless of neighbour Button? Here is screenshot of problem:
Don't use layouts if you want to place your items with absolute position. Use anchors instead:
Item {
anchors.fill: parent
Rectangle
{
anchors.fill: parent
color: "#e4e4e4"
border.width: 0
border.color: "#e4e4e4"
radius: 32
ColumnLayout
{
anchors.fill: parent
spacing: 8
Item {
Layout.fillWidth: true
Rectangle
{
id: buttonBack
color: "transparent"
anchors.fill: parent
Image
{
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
sourceSize.width: 128
sourceSize.height: 128
smooth: true
antialiasing: true
source: (buttonBack.isPressed===true)?"http://icons.iconarchive.com/icons/iconarchive/red-orb-alphabet/256/Letter-A-icon.png"
:"http://www.iconarchive.com/download/i14559/iconarchive/red-orb-alphabet/Arrow.ico"
} // Image
} // Rectangle
Text
{
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: "black"
text: qsTr("TEST TEXT")
font.pointSize: 24
} // Text
}
} // RowLayout
} // Rectangle
}

QML: TableView and Columns

I noticed that the column that is on the right always overlaps the data from the column that is on the left. How to change this behavior?
The panel with shadow is defined into TableViewColumn.delegate. I need the panel to overlap the neighbor in the right cell.
// Minimal code example that represent a problem!
Page {
TableView {
anchors.fill: parent
selectionMode: 1
TableViewColumn {
role: "login"
title: "Login"
width: 100
delegate: Rectangle {
color: "transparent"
anchors.fill: parent
Rectangle {
anchors.verticalCenter: parent.verticalCenter
height: 40
width: 150
color: "green"
}
}
}
TableViewColumn {
role: "fullName"
title: "FullName"
width: 100
delegate: Rectangle {
color: "transparent"
anchors.fill: parent
Rectangle {
anchors.verticalCenter: parent.verticalCenter
height: 30
width: 150
color: "red"
}
}
}
TableViewColumn {
role: "status"
title: "Status"
width: 100
delegate: Rectangle {
color: "transparent"
anchors.fill: parent
Rectangle{
anchors.verticalCenter: parent.verticalCenter
height: 20
width: 150
color: "blue"
}
}
}
model: ListModel {
ListElement { text: "ghdjbf" }
ListElement { text: "sgkjdnf" }
ListElement { text: "sgkjdnf" }
ListElement { text: "sgkjdnf" }
ListElement { text: "sgkjdnf" }
}
property Component headerDelegate: BorderImage {
property bool sortSwitcher: false
height: 40
id: tableHeader
objectName: "TableHeader"
Rectangle {
id: viewableSection
anchors.fill: parent
color: "white" // "#f2f2f2"
Text {
id: textItem
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
anchors.leftMargin: 25
font.pixelSize: 11
font.family: "Roboto"
text: styleData.value
font.bold: true
elide: Text.ElideRight
color: "#646464"
renderType: Text.NativeRendering
}
Rectangle {
id: bottomHeaderBorder
anchors.top: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: "#ebebeb"
}
Rectangle {
id: headerSeparator
z: 1
anchors.left: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.bottomMargin: 8
anchors.topMargin: 8
width: 1
color: "lightgrey"
MouseArea {
id: mouseAreaSeparator
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.SizeHorCursor
onEntered: {
mouseAreaSeparator.cursorShape = Qt.SizeVerCursor
}
}
}
}
}
property Component rowDelegate: Rectangle {
id: rowDel
objectName: "RowDelegate"
height: 50
//property color selectedColor: styleData.hasActiveFocus ? primaryColor : secondaryColor
property bool selectionMaskVisible
property bool selected: false
Rectangle {
id: rowSelectionMask
anchors.fill: parent
color: rowDel.selectionMaskVisible ? "#f2f2f2" : "#ffffff"
visible: parent.activeFocus ? false : true
z: parent.activeFocus ? 1 : 2
}
Rectangle {
id: activeFocusMask
anchors.fill: parent
color: parent.activeFocus ? styleData.row !== undefined ? secondaryColor : "White" : "White"
opacity: styleData.row !== undefined ? 0.9 : 0
z: parent.activeFocus ? 2 : 1
}
MouseArea {
id: rowMouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
onEntered: {
if (styleData.row !== undefined)
{
rowDel.selectionMaskVisible = true
}
}
onExited: {
rowDel.selectionMaskVisible = false
}
}
Rectangle {
id: bottomBorder
objectName: "BottomBorder"
z: 2
anchors.bottom: parent.bottom
height: 1
width: parent.width
color: "#ebebeb"
opacity: styleData.row !== undefined ? 1 : 0
}
Rectangle {
id: separator
z: 1
anchors.left: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.bottomMargin: 1
anchors.topMargin: 1
width: 1
color: "red"
}
}
}
}
Judging from the code there is no clean solution to it.
But as you can see, the delegate of the TableViewColumn is instantiated by a Loader via a Repeater into a Row.
So to change get the first column on top of the second column, we need to change the z-index - but not of the delegate itself (as this would only affect the children of the same Loader) but of the Loader. This can be achieved e.g in the Component.onCompleted-handler.
TableViewColumn {
role: "login"
title: "Login"
width: 100
delegate: Rectangle {
color: "transparent"
anchors.fill: parent
Component.onCompleted: parent.z = 3 // <- Put the loader on top of its siblings
Rectangle {
anchors.verticalCenter: parent.verticalCenter
height: 40
width: 150
color: "green"
}
}
Component.onCompleted: console.log(Object.keys(this))
}

Custom Button with conditional image and conditional text

I have the following custom QML Button:
import QtQuick.Controls 1.4
import QtQuick 2.5
import QtQuick.Layouts 1.2
import QtMultimedia 5.5
Rectangle {
id: ueButton
property string ueText: ""
property string ueIconPath: ""
width: 256
height: 128
signal ueSignalButtonClicked
gradient: Gradient {
GradientStop {
position: 0
color: "#ffffff"
SequentialAnimation on color {
id: ueButtonClickAnimation
loops: 1
running: false
ColorAnimation {
from: "#ffffff"
to: "#000000"
duration: 25
} // ColourAnimation
ColorAnimation {
from: "#000000"
to: "#ffffff"
duration: 25
} // ColorAnimation
} // SequentialAnimation
} // GradientStop
GradientStop {
position: 0.418
color: "#000000"
} // GradientStop
} // Gradient
border.color: "steelblue"
border.width: 1
radius: 4
antialiasing: true
smooth: true
ColumnLayout {
anchors.fill: parent
antialiasing: true
Image {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignTop
Layout.margins: 8
asynchronous: true
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
fillMode: Image.PreserveAspectFit
smooth: true
source: ueIconPath
} // Image
Text {
text: ueText
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter
Layout.topMargin: 8
Layout.leftMargin: 8
Layout.rightMargin: 8
Layout.bottomMargin: 16
color: "#ffffff"
font.bold: true
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pointSize: 16
textFormat: Text.RichText
} // Text
} // ColumnLayout
MouseArea {
id: ueButtonMouseArea
antialiasing: true
anchors.fill: parent
onClicked: {
ueButtonClickAnimation.running=true
ueSignalButtonClicked()
}
} // MouseArea
} // ueButton
This works fine, but what I want to do now is to solve the following two specular issues:
If urtext is empty the corresponding text is ignored and whole ColumnLayout place is reserved for Image
If ueIconPath is empty, the corresponding image is ingnored and the whole ColumnLayout is reserved for Text
How can I achieve that?
As #BaCaRoZzo already suggested, using styles is preferable solution in this case since the item itself is still Button and so you can use all its properties and signals, including text property to pass your ueText text.
As for hiding elements inside, you can use visible property as suggested below:
UeButton.qml
Button {
id: ueButton
style: ButtonStyle {
background: Rectangle {
color: control.pressed ? "#CCC" : "#DEDEDE"
border.width: 1
border.color: "#999"
radius: 3
}
label: ColumnLayout {
id: layout
spacing: 10
Image {
Layout.alignment: Qt.AlignHCenter
source: control.iconSource
visible: control.iconSource !== ""
}
Text {
text: control.text
visible: control.text !== ""
}
}
}
}
Now using of this component is similar to regular Button:
UeButton {
anchors.centerIn: parent
text: "Some text"
iconSource: "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
}
Commenting out text or iconSource will change the button view

ColumnLayout items size proportions

I have QML Item with one ListView (bottom part of Item) and one GridView (upper part of Item:
import QtQuick 2.5
import QtQuick.Layouts 1.2
Item
{
width: 768
height: 512
ColumnLayout
{
id: ueCentralWidget
anchors.centerIn: parent
anchors.fill: parent
spacing: 8
Rectangle
{
Layout.fillWidth: true
Layout.fillHeight: true
border.color: "#4682b4"
radius: 16
gradient: Gradient
{
GradientStop
{
position: 0
color: "#ffffff"
} // GradientStop
GradientStop
{
position: 1
color: "#000000"
} // GradientStop
} // Gradient
ColumnLayout
{
anchors.centerIn: parent
anchors.fill: parent
UeProductSelector
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
antialiasing: true
clip: true
} // UeProductSelector
UeCategorySelector
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
antialiasing: true
clip:true
} // UeCategorySelector
} // ColumnLayout
} // Rectangle
} // ColumnLayout
}
I want to lower ListView occupy 1/3 of Item size and GridView occupy 2/3 of Item size., Adding task screenshot:
How do I achieve such task?
Using fillWidth and fillHeight on all Items of my Layout was the problem. Setting the preferredHeight to parent.height/3 and leaving the other with fillHeigh solved the issue for me.
Here is the working code:
import QtQuick 2.5
import QtQuick.Layouts 1.2
Item
{
width: 768
height: 512
ColumnLayout
{
id: ueCentralWidget
anchors.centerIn: parent
anchors.fill: parent
spacing: 8
Rectangle
{
Layout.fillWidth: true
Layout.fillHeight: true
border.color: "#4682b4"
radius: 16
gradient: Gradient
{
GradientStop
{
position: 0
color: "#ffffff"
} // GradientStop
GradientStop
{
position: 1
color: "#000000"
} // GradientStop
} // Gradient
ColumnLayout
{
anchors.centerIn: parent
anchors.fill: parent
UeProductSelector
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
antialiasing: true
clip: true
} // UeProductSelector
UeCategorySelector
{
Layout.fillWidth: true
Layout.preferredHeight: parent.height/3
Layout.margins: 8
antialiasing: true
clip:true
} // UeCategorySelector
} // ColumnLayout
} // Rectangle
} // ColumnLayout
}