QML Rectangle Object coming in wrong place - qml

I am just trying to create 4 rectangles with 3 next to each other and 4th one is below the 3rd rectangle and my qml looks like below
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Rectangle")
Item{
anchors.centerIn: parent
Rectangle {
id: firstRect
width:50
height:50
color: "#ff0000"
}
Rectangle {
id: secondRect
width:firstRect.width
height: firstRect.height
color: "blue"
//opacity: 0.5
anchors.left: firstRect.right
}
Rectangle {
id: thirdRect
width:firstRect.width
height: firstRect.height
color: "green"
//opacity: 0.5
anchors.left: secondRect.right
}
Rectangle {
id: fourthrect
width:firstRect.width
height: firstRect.height
color: "green"
//opacity: 0.5
anchors.top: thirdRect.bottom
}
}
}
But i am getting the 4th rectangle below the first rectangle like below even though my anchor is thirdRect.Bottom what am i doing wrong

Nearly there, you're close. Just need to anchor it horizontally under the third rectangle.
Rectangle {
id: fourthrect
width:firstRect.width
height: firstRect.height
color: "green"
anchors.top: thirdRect.bottom
anchors.left: thirdRect.left // <-- this
}
Note that, assuming both the third and fourth rectangles have the same width, it's also possible to use anchors.right: thirdRect.right or anchors.horizontalCenter: thirdRect.horizontalCenter.
Setting anchors.top: thirdRect.bottom will only anchor the item vertically, but not horizontally.

Related

QML - How do I make the TabButtons in TabBar visible?

I'm using qtcreator 4.4.1 with qt 5.9.2-1 on linux
I'm trying to create a tabbar with a stackview so that I can switch between the different tabs. But the tabbuttons in the tabbar never show up, and they aren't functional either if I click the area where they should have been.
I've tried adding all sorts of colored rectangles to see if I could somehow bring it to the surface, but it never shows... And I also added visible: true on most of the components. Also I tried to make sure everything has a width and height. But nonetheless, I still am unable to see it.
This is what it looks like
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.3
import QtQuick.Templates 2.2
ApplicationWindow {
id: root
flags: Qt.FramelessWindowHint
visible: true
width: 382
height: 748
Column {
id: column1
width: parent.width
height: parent.height
visible: true
TabBar {
id: bar
width: parent.width
height: 50
visible: true
TabButton {
visible: true
text: qsTr("Fruit")
width: parent.width
height: parent.height
Rectangle {
anchors.fill: parent
color: "#ff0000"
visible: true
}
}
TabButton {
visible: true
text: qsTr("Vegetables")
width: parent.width
height: parent.height
Rectangle {
anchors.fill: parent
color: "#00ff00"
visible: true
}
}
TabButton {
text: qsTr("Demons")
width: parent.width
height: parent.height
Rectangle {
anchors.fill: parent
color: "#0000ff"
visible: true
}
}
}
StackLayout {
width: parent.width
height: parent.height
visible: true
currentIndex: bar.currentIndex
Item {
id: fruitTab
Rectangle {
anchors.fill: parent
color: "#ff0000"
visible: true
}
}
Item {
id: vegetableTab
Rectangle {
anchors.fill: parent
color: "#00ff00"
visible: true
}
}
Item {
id: demonTab
Rectangle {
anchors.fill: parent
color: "#0000ff"
visible: true
}
}
}
}
}
I also tried the simple example given by the qt docs: https://doc.qt.io/qt-5/qml-qtquick-controls2-tabbar.html#details but that didn't work either.
It looks like this
In addition to what #derM said (I would just leave out the width and height assignments altogether), the last import is a problem:
import QtQuick.Templates 2.2
Since the templates and controls have a one-to-one mapping of type names, this will cause the controls types to be shadowed by the ones from templates (since the templates import comes last).
You should always import the templates into their own namespace if you're also importing the controls:
import QtQuick.Templates 2.2 as T
http://doc.qt.io/qt-5/qtqml-syntax-imports.html#import-types explains this in detail:
This import allows multiple modules which provide conflicting type names to be imported at the same time, however since each usage of a type provided by a module which was imported into a qualified namespace must be preceded by the qualifier, the conflict is able to be resolved unambiguously by the QML engine.
In your example it looks like you're not using the templates at all, so you can just remove the import.
Try to remove the width in your TabButtons.
The problem seems to be, the dynamic sizing of the buttons.
You set them to be of the same width as the tab bar. So each button would fill the whole bar on its own.
When it tries to layout this, it obviously fails.
The same goes, if you set all of them, e.g. to width = parent.width / 2 as the parent's width is determined by the width of the children.
You need to either set the width of the buttons in relation to the TabBars width, by using myTabBarsId.width or you can just leave it out and let it be sized dynamically.
TabBar {
id: bar
width: parent.width
height: 50
visible: true
TabButton {
width: bar.width / 2 // Define width based on the `TabBar` width
text: qsTr("Fruit")
height: parent.height
}
TabButton {
text: qsTr("Vegetables")
height: parent.height
}
TabButton {
text: qsTr("Demons")
height: parent.height
}
}

How to keep qml Rectangle border from overlapping contents?

I want a Rectangle to auto-size itself to fit exactly around its visual children. If there is no border, then the following works great:
Rectangle {
width: childrenRect.width+(border.width*2)
height: childrenRect.height+(border.width*2)
...
}
HOWEVER, if the Rectangle has a border, the children will overlap it. I tried unsuccessfully wrapping the children in a container (Column in the example below) and using anchor.margins to shift the container over to miss the Rectangle's borders.
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 600; height: 600
Rectangle {
id: rect
border.width : 20
border.color: "yellow"
clip: true
width: childrenRect.width+(border.width*2)
height: childrenRect.height+(border.width*2)
Column {
anchors.margins: rect.border.width // does not work
Text { height: 40; text: "FoooooooooooooooMumble" }
Text { height: 40; text: "Bar" }
Button { height: 40; text: "press me" }
}
}
}
Can someone suggest how to do this?
For anchors.margins to work, the border anchors must be set (the margin space is relative to those). For example:
Column {
anchors.margins: rect.border.width
anchors.left: rect.left
anchors.top: rect.top
...
}

QML: Center variable text and image

I need to horizonally center a variable-length text (red box) and an image (yellow box) in a big box (green box). The text shall wrap if it does not fit the box.
Existing code:
Item {
id: bigBox
x: 255
y: 0
width: 800
height: 100
Image {
id: imageBox
source: "image.png"
width: 52
height: 46
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Image.AlignLeft
verticalAlignment: Image.AlignVCenter
fillMode: Image.Pad
}
Text {
id: textBox
anchors.left: symbol.right
anchors.leftMargin: 12
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: qsTr("heading text")
font.pixelSize: 36
font.bold: true
horizontalAlignment: Text.AlignCenter
}
}
Update:
Actual running code and a real screenshot showing the problem:
import QtQuick 2.0
Rectangle {
id: mask
x: 0
y: 0
width: 800
height: 430
color: "#FFFFFF"
property int pageState: 0
Rectangle {
x: 0
y: 0
width: 111
height: 100
color: "#0000FF"
}
Item {
id: whitespace
x: 117
y: 0
width: 800-x
height: 100
Row {
anchors.centerIn: parent
Image {
id: symbol
source: "../img/pepper.png"
width: 52
height: 46
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.Pad
}
Text {
id: heading
property var texts: ["Active Blabla","Active Blaaaaaaah Blaaaah ","Active Blabla and Blaaaaaaah Blaaaah"]
anchors.verticalCenter: parent.verticalCenter
color: "#333191"
text: texts[pageState]
font.family: "Liberation Sans"
font.pixelSize: 36
font.bold: true
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
textFormat: Text.PlainText
width: Math.min(150,contentWidth)
}
}
}
Rectangle {
id: stage
x: 0
y: 106
width: parent.width
height: parent.height-y
color: "#FFFF00"
}
Timer {
interval: 1000 // milliseconds
triggeredOnStart: true
repeat: true
running: true
onTriggered: {
pageState=(pageState+1)%3;
}
}
}
The white area top right is the green box in the first picture. The timer simply runs through the three texts, like the real application would do.
Changing the first parameter of Math.min() to 600 does not change anything.
My set of hacks to solve that problem:
Item {
// ...
Text {
function escapeHTML(text)
{
return text.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""");
}
function toHTML(imageUrl,text)
{
var textlines=escapeHTML(text).replace(/\r?\n/,"\n").split("\n");
var retval="<center>";
retval=retval+'<table><tr>';
if (imageUrl!="") {
retval=retval+'<td rowspan="'+(textlines.length)+'"><img src="'+imageUrl+'"></td>';
retval=retval+'<td rowspan="'+(textlines.length)+'"> </td>';
}
for (var i=0; i<textlines.length; i++) {
if (i>0) {
retval=retval+"<tr>";
}
retval=retval+'<td>'+textlines[i]+'</td></tr>';
}
retval=retval+'</table>';
retval=retval+"</center>";
return retval;
}
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
textFormat: Text.RichText
text: toHtml("../img/pepper.png",qsTr("heading"))
}
}
<center> centers the text in the available space, but not the image
(it stays left - bug!).
<table> can be centered by <center>, and it can contain the
image.
Wrapping does not work as expected, so the translated text returned
by qsTr() has to contain linebreaks at the right positions.
toHTML() splits at the linebreaks and generates table rows from that.
The image needs a table cell with rowspan, or else the image is placed too high relative to the text.
And finally, verticalAlignment: Text.AlignVCenter places all of that vertically centered -- except for the table borders that I luckily don't need. (If you are bored, add border=1 to the <table> tag.)
And no, the HTML and CSS subset supported by Text.RichText does not support vertical alignment. The rendering engine behaves like ancient browsers, you have to stack hacks and workarounds as if it was still 1996.
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.2
Item {
id: bigBox
width: 800
height: 100
Row {
anchors.centerIn: parent
Image {
anchors.verticalCenter: parent.verticalCenter
source: "blue.png"
}
Text {
anchors.verticalCenter: parent.verticalCenter
// maximum width of the text
width: Math.min(150, contentWidth)
text: qsTr("heading")
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
}
}
}

QML Row element refuses to work

I know I should be using Row, Column etc. rather than items anchored by ID to make my code simpler and easier to read. But they refuse to work most of the time. For example, in this case:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
ListView {
id: listView
anchors.fill: parent
topMargin: spacing
anchors.leftMargin: spacing
anchors.rightMargin: spacing
clip: true
spacing: 0.5 * pxPermm
model: SqlQueryModel {}
delegate: Rectangle {
id: delegateItem
color: "white"
height: 14 * pxPermm
width: listView.width
clip: true
Row {
id: row
anchors.fill: delegateItem
spacing: pxPermm
Image {
height: row.height
width: height
source: "qrc:/resources/ryba.jpg"
fillMode: Image.PreserveAspectCrop
}
Item {
id: textItem
height: row.height
Label {
anchors.left: textItem.left
anchors.top: textItem.top
text: nazov
font.bold: true
}
Label {
anchors.left: textItem.left
anchors.bottom: textItem.bottom
text: cas
}
}
}
}
}
This shows two Labels on the top of an Image in the delegate of list view. Not two labels to the right of the image, as you would expect. However, this code works:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
ListView {
id: listView
anchors.fill: parent
topMargin: spacing
anchors.leftMargin: spacing
anchors.rightMargin: spacing
clip: true
spacing: 0.5 * pxPermm
model: SqlQueryModel {}
delegate: Rectangle {
id: delegateItem
color: "white"
height: 14 * pxPermm
width: listView.width
clip: true
Row {
id: row
anchors.fill: delegateItem
spacing: pxPermm
Image {
height: row.height
width: height
source: "qrc:/resources/ryba.jpg"
fillMode: Image.PreserveAspectCrop
}
Label {
text: nazov
font.bold: true
}
}
}
}
Of course I need to show more than one label in the delegate. What am I missing here?
It turns out that Item has zero width by default. The code works properly after the width is set:
Item {
id: textItem
height: row.height
width: childrenRect.width
// labels etc
}

Center the label in a ComboBox element with a custom ComboBoxStyle

I am using QtQuick.Controls 1.0 and QtQuick.Controls.Styles 1.0 and I can't find a way to properly align the label of the ComboBox vertically and on the right.
This is my current code
import QtQuick 2.0
import QtQuick.Controls 1.0
import QtQuick.Controls.Styles 1.0
ComboBox {
id: comboCategories
width: 230
height: 30
style: ComboBoxStyle {
background: Rectangle {
id: rectCategory
width: comboCategories.width
height: comboCategories.height
color: "white"
}
label: Text {
anchors.verticalCenter: parent.verticalCenter
anchors.right: background.right
font.pointSize: 12
color: "#808080"
text: control.currentText
}
}
}
But the label stays in the top left of my element and does not seem to be affected by the anchors. I also tried to replace parent with control or background with no effect
I don't exactly know the reasoning behind this but if I wrap my Text element in an Item then I can properly
import QtQuick 2.0
import QtQuick.Controls 1.0
import QtQuick.Controls.Styles 1.0
ComboBox {
id: comboCategories
width: 230
height: 30
style: ComboBoxStyle {
background: Rectangle {
id: rectCategory
width: comboCategories.width
height: comboCategories.height
color: "white"
}
label: Item {
anchors.fill: parent
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 5
font.pointSize: 12
color: "#808080"
text: control.currentText
}
}
}