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

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

Related

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

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

How to properly bind values to 'from' and 'to', inside a NumberAnimation?

I want to create a horizontal scrolling text animation (enter at the right side, go through the screen, exit at the left side, repeat).
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
id: root
visible: true
Rectangle {
id: scrollLine
anchors.fill: parent
color: "black"
Text {
id: scrollText
color: "white"
text: "This is a test"
font.pixelSize: parent.height * 0.5
anchors.verticalCenter: parent.verticalCenter
x: scrollLine.width
NumberAnimation on x {
id: scrollAnimation
from: scrollLine.width; to: -scrollText.width
duration: 5000
loops: Animation.Infinite
running: true
}
}
}
}
The problem is, that my text acts weird. Appears left side, scrolls left with two characters, repeat... Something is wrong at the binding
from: scrollLine.width; to: -scrollText.width,
but I have no idea what.
Ah, this is weird! :)
The first thing I can see is that this
x: scrollLine.width
does nothing. The NumberAnimation runs immediately, causing the x value of the Text to be set, so we can remove that code to make it easier to find the problem.
The next thing to do is to print out the widths of the items:
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
id: root
visible: true
Rectangle {
id: scrollLine
anchors.fill: parent
color: "black"
onHeightChanged: print("rectangle height", height)
Text {
id: scrollText
color: "white"
text: "This is a test"
font.pixelSize: parent.height * 0.5
anchors.verticalCenter: parent.verticalCenter
onWidthChanged: print("text width", width)
NumberAnimation on x {
id: scrollAnimation
from: scrollLine.width
to: -scrollText.width
duration: 5000
loops: Animation.Infinite
running: true
}
}
}
}
That gives us:
qml: text width 72.078125
qml: rectangle height 160
qml: text width 443.734375
Ok, it's weird that the text size changes width, but... it indirectly depends on the size of the window, right? We set its font.pixelSize to parent.height * 0.5. It just so happens that the window size is determined after the Text gets its initial size. However, being a declarative language, you'd think this should work.
Let's check the from and to values of the animation:
onFromChanged: print("from", from)
onToChanged: print("to", to)
Now we get:
qml: from 0
qml: to 0
qml: text width 72.078125
qml: to -72.078125
qml: from 160
qml: rectangle height 160
qml: text width 443.734375
qml: to -443.734375
They are initially incorrect, sure, but they do eventually become correct. This smells like a bug. Let's double check by printing out the x position of the Text:
qml: x -0.576625
...
qml: x -71.4654609375
That's not right. It seems like a bug. I thought it was, too, but then I checked the documentation:
If the NumberAnimation is defined within a Transition or Behavior, this value defaults to the value defined in the starting state of the Transition, or the current value of the property at the moment the Behavior is triggered.
You're not using a Behavior, although the syntax looks very similar. A bit more searching reveals the documentation for the on keyword:
The animation starts as soon as the rectangle is loaded, and will automatically be applied to its x and y values.
So, it's not a bug. You'll have to give the animation sensible from and to values somehow. One solution is to hard-code the values:
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
id: root
width: 250
height: 250
visible: true
Rectangle {
id: scrollLine
anchors.fill: parent
color: "black"
Text {
id: scrollText
color: "white"
text: "This is a test"
font.pixelSize: parent.height * 0.5
anchors.verticalCenter: parent.verticalCenter
NumberAnimation on x {
id: scrollAnimation
from: root.width
to: -1000
duration: 5000
loops: Animation.Infinite
running: true
}
}
}
}
The best solution would probably be not to rely on the window's height for the font size, though. The default font size chosen by Qt is legible on all platforms that provide sensible DPI information, so you would be better off multiplying that by some factor:
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
id: root
width: 250
height: 250
visible: true
Rectangle {
id: scrollLine
anchors.fill: parent
color: "black"
FontMetrics {
id: fontMetrics
}
Text {
id: scrollText
color: "white"
text: "This is a test"
font.pixelSize: fontMetrics.font.pixelSize * 8
anchors.verticalCenter: parent.verticalCenter
NumberAnimation on x {
id: scrollAnimation
from: root.width
to: -1000
duration: 5000
loops: Animation.Infinite
running: true
}
}
}
}
You code works as expected with a little modification. Instead of using font.pixelSize: parent.height*0.5, I used a fixed size point. Try this
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
id: root
visible: true
Rectangle {
id: scrollLine
anchors.fill: parent
color: "black"
Text {
id: scrollText
color: "white"
text: "This is a test"
font.pixelSize: 150; //////// Changed this
anchors.verticalCenter: parent.verticalCenter
x: scrollLine.width
NumberAnimation on x {
id: scrollAnimation
from: scrollText.width; to: -scrollText.width
duration: 5000
loops: Animation.Infinite
running: true
}
}
}
}

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
}