How to keep qml Rectangle border from overlapping contents? - qml

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
...
}

Related

QML Rectangle Object coming in wrong place

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.

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
}
}

Unable to position custom styled Tumbler

I am trying to give a Tumbler my own style. I declare the Tumbler like this:
Tumbler {
style: MyTumblerStyle {}
height: UIConstants.smallFontSize * 10
width: UIConstants.smallFontSize * 3
TumblerColumn {
model: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]
}
}
where MyTymblerStyle is defined like this:
TumblerStyle {
id: root
visibleItemCount: 5
background: Rectangle {}
foreground: Item {}
frame: Item {}
highlight: Item {}
delegate: Item {
id: delRoot
implicitHeight: (control.height) / root.visibleItemCount
Item {
anchors.fill: parent
Text {
text: styleData.value
font.pixelSize: UIConstants.smallFontSize
font.family: UIConstants.robotoregular
anchors.centerIn: parent
scale: 1.0 + Math.max(0, 1 - Math.abs(styleData.displacement)) * 0.6
color: styleData.current?UIConstants.color:"black"
opacity: 1 - Math.abs(styleData.displacement/(root.visibleItemCount-3))
}
}
}
}
I use it in a Row like this:
Row {
MyTumbler {}
StandardText {
color: UIConstants.color
text: "Uhr"
}
}
Now, the result looks like this:
As you can see, the "Uhr" text center is aligned to the top of the Tumbler. Also the Row does not seem to recognize the real width of the Tumbler.
Why? It does work when I do not use MyTumblerStyle.
The problem isn't your style, it's the width assignment.
It helps to break out the Rectangles at a time like this:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Extras 1.3
ApplicationWindow {
title: qsTr("Hello World")
width: 300
height: 600
visible: true
Column {
anchors.centerIn: parent
Tumbler {
id: tumbler
width: 30
TumblerColumn {
model: 25
}
Component.onCompleted: print(width, height, implicitWidth, implicitHeight)
}
Rectangle {
width: tumbler.implicitWidth
height: tumbler.implicitHeight
color: "transparent"
border.color: "blue"
Text {
text: "Tumbler implicit size"
anchors.fill: parent
wrapMode: Text.Wrap
}
}
Rectangle {
width: tumbler.width
height: tumbler.height
color: "transparent"
border.color: "blue"
Text {
text: "The size you gave"
anchors.fill: parent
wrapMode: Text.Wrap
}
}
}
}
(I don't have access to UIConstants, so I guess the width you set)
The implicitWidth of Tumbler is calculated based on the width of each individual TumblerColumn. This allows you to set individual widths for columns, something that is necessary for scenarios where some are wider than others, for example:
So, you should also set the width of your column, or, preferably, only set the width of your column, and not the entire Tumbler:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Extras 1.3
ApplicationWindow {
width: 300
height: 600
visible: true
Row {
anchors.centerIn: parent
Tumbler {
id: tumbler
TumblerColumn {
model: 25
width: 30
}
}
Text {
text: "Uhr"
}
}
}
This also explains why the Text is weirdly positioned; the Row sees 30 pixels, but the column still has its original (much wider) width.

Qml RightToLeft Alignment placeholderText

Greetings Dear Programmers ;))
Im Recently entered the world of Qt programming , I want Text PlaceHolder Align From right to left'm grateful for help Me enter image description here
Everything you need to know about Right to Left interfaces is explained in QML Right-to-left User Interfaces.
You need at least the following properties in your Text type:
horizontalAlignment: Text.AlignLeft
LayoutMirroring.enabled: true
width: parent.width // whatever you want here, but 'width' must be present.
A quick example:
import QtQuick 2.4
import QtQuick.Controls 1.4
ApplicationWindow {
id: mainWindow
width: 400
height: 300
Rectangle {
id: rect1
anchors.fill: parent
color: "lightsteelblue"
Rectangle {
height : 20
width : parent.width / 2
anchors.centerIn: parent
color : "white"
Text {
text: "هذا هو مجرد اختبار"
horizontalAlignment: Text.AlignLeft
LayoutMirroring.enabled: true
width: parent.width
}
}
}
}

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
}