Align QML TabView content with another item, so that tabBar overlaps with that item - qml

I would like the actual Tab contents inside a TabView to anchor or line up to the bottom of another visual element. In this case the tabBar at the top would overlap with the other element in question.
My problem is that I don't know how to get the y coordinate of the Tab contents of the TabView or alternatively, how to get the height of the tab buttons in the tabBar so I can offset the alignment based on it.
I can think of 2 ways to solve this, both of which are clunky:
Option 1 -- I could make a TabView with no contents, which sits inside my other element. Then I could make a second TabView with tabsVisible = false. Then link the 2 together.
Option 2 -- I could override tab: in TabViewStyle, set a height for it from a property, that way I could offset my TabView.y based on the tabBar height.
Option 3: Somehow get the y coordinate of a Tab content within TabView (relative to the TabView or the parent item) or somehow get the existing tab (button) height. I have no idea how to do either of these.
Options 1 and 2 seem very clunky. Any ideas?

Actually you can get this information very easily. TabView define a contentItem property, which holds the content item of the tab view. The tab button height is therefore tabView.height - tabView.contentItem.height
Example:
import QtQuick 2.2
import QtQuick.Controls 1.1
Item {
width: 350
height: 150
TabView
{
id: tabview
height: parent.height
width: parent.width/2
Component.onCompleted: {addTab("1");addTab("2")}
}
Column
{
anchors.left: tabview.right
anchors.right: parent.right
Rectangle
{
width: parent.width
height: tabview.height-tabview.contentItem.height
color: "red"
}
Rectangle
{
width: parent.width
color: "yellow"
height: tabview.contentItem.height
}
}
}

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

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

Center elements inside Scrollview

I have a problem with centering QML objects in a ScrollView. I want to scroll the images and other QML elements and they should be centered. But they are always sticked to the top left angle.
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Window 2.0
ApplicationWindow{
id: appWindow
width:Screen.width
height:Screen.height
visible: true
ScrollView {
anchors.fill: parent
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
width: 800
height: 800
color : "yellow"
}
}
}
You have two aspects to take in account. Directly from the docs:
Only one Item can be a direct child of the ScrollView and the child is implicitly anchored to fill the scroll view.
So you could not have more than one Rectangle, just a container for all the Rectangles (which actually are images, as stated in your question).
Moreover it should be noted, again from the docs, that:
The width and height of the child item will be used to define the size of the content area.
Hence, you need only one child for the ScrollView and ensure that it takes the correct size from the parent. I would use a ColumnLayout for the purpose. Final sample code here:
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Window 2.0
import QtQuick.Layouts 1.1
ApplicationWindow{
id: appWindow
width: 200
height: 100
visible: true
ScrollView {
anchors.fill: parent
ColumnLayout { // unique child
spacing: 10
width: appWindow.width // ensure correct width
height: children.height // ensure correct height
// your children hereon...
Repeater {
model: 4
delegate: Rectangle {
Layout.alignment: Qt.AlignHCenter
width: 50
height: 50
color : "yellow"
}
}
}
}
}
EDIT
According to the OP the provided solution does not perfectly meet his needs and that's pretty reasonable. In particular:
no horizontal scrollbar is shown if the window is resized horizontally
the horizontal scrollbar is shown as soon as the vertical one is shown
Both the problems are related to the approach used. Problem 1 is caused by the binding between the parent width and the ScrollView width: since the visible width is always equal to the total width, no horizontal scroll is shown, even if the contained items are larger than the window. Problem 2 is a consequence of the 1: since the width is equal to application, as soon as a vertical scrollbar is added, the horizontal one is also added to show the horizontal space covered by the vertical scrollbar.
Both the problems can be solved by changing the width binding to be either equal to the contained items width (to solve problem 1) or equal to the width of the viewport (solve problem 2), as also discussed in this other answer. Finally, anchoring should be removed to avoid binding loops. Here is a complete example working as expected:
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
ApplicationWindow{
id: appWindow
width: 200
height: 100
visible: true
ScrollView {
id: scroller
width: appWindow.width // NO ANCHORING TO AVOID binding loops!
height: appWindow.height
ColumnLayout { // <--- unique child
spacing: 10
width: Math.max(scroller.viewport.width, implicitWidth) // ensure correct width
height: children.height // ensure correct height
// your children hereon...
Repeater {
model: 3
delegate: Rectangle {
Layout.alignment: Qt.AlignHCenter
width: 150
height: 150
color : "yellow"
}
}
}
}
}
is bound to the window width horizontal scrolls are not shown, even if contained items are larger than the window
From the doc (http://qt-project.org/doc/qt-5/qml-qtquick-controls-scrollview.html) :
Only one Item can be a direct child of the ScrollView and the child is implicitly anchored to fill the scroll view.
So you can't achieve what you want by anchoring the content. You have to change the size and the anchoring of the ScrollView
For example :
ApplicationWindow{
id: appWindow;
width:Screen.width;
height:Screen.height;
visible: true;
ScrollView
{
anchors.centerIn: parent;
width: Math.min(content.width + 30, appWindow.width);
height: Math.min(content.height, appWindow.height);
Rectangle
{
id: content;
width: 800;
height: 800;
color : "yellow"
}
}
}
You can insert a Rectangle or other similar QML items you like as a middle layer between ScrollView and the QML item you need to center and set its color to "transparent". This should be a cross-platform solution.
I have modified your code for example:
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Window 2.0
ApplicationWindow {
id: appWindow
width:Screen.width
height:Screen.height
visible: true
ScrollView {
anchors.fill: parent
Rectangle {
width: Math.max(appWindow.width, rect.width)
height: Math.max(appWindow.height, rect.height)
color: "transparent"
Rectangle {
id: rect
anchors.centerIn: parent
width: 800
height: 800
color : "yellow"
}
}
}
}
I use Qt 5.5.

Hide the highlight of a ListView while scrolling

I am building a Qt5 application based on Qt-Quick 2 for the UI. I have an issue while displaying a ListView with an highlight component. When I scroll the ListView the highlight rectangle is visible outside of the ListView and I can't find a way to avoid it.
Here is an example of the issue with a minimal QML file:
import QtQuick 2.0
Rectangle {
width: 360; height: 600
ListView {
width: 350; height: 200
anchors.centerIn: parent
id: myList
model: myModel
highlight: highlightBar
delegate: Item {
width: 400; height: 20
Text { text: name }
MouseArea {
id: mArea
anchors.fill: parent
onClicked: { myList.currentIndex = index; }
}
}
}
Component {
id: highlightBar
Rectangle {
width: parent.width; height: 20
color: "#FFFF88"
}
}
ListModel {
id: myModel
}
/* Fill the model with default values on startup */
Component.onCompleted: {
for(var i = 0; i < 100; i++) {
myModel.append({ name: "Big Animal : " + i});
}
}
}
Is there a way to "limit" a component to its parent borders or to hide the highlight component while scrolling?
As reported by the documentation:
Note: Views do not enable clip automatically. If the view is not clipped by another item or the screen, it will be necessary to set clip: true in order to have the out of view items clipped nicely.
Hence, what you are experiencing is a common behaviour and you should either 1) clip the view via other Items (e.g. a header Rectangle and a footer Rectangle with z:infinite or simply set the clip property to true, i.e.
ListView{
//...
clip:true
//...
}
Clipping has some perfomance disavantages which can greatly affect the application as it grows. Hence, its usage, especially outside the views scenario, should be evaluated carefully.

ListView highlight item isn't shown

I'm trying to highlight the currently selected item in a ListView. Below is the code I'm using; for some reason, while a similar code works perfectly in another ListView of this application, here the SelectedRectangle item is never displayed, althought the selected item changes when it should.
Rectangle {
id: deviceTree
width: (window.width * 2) / 3
height: 400
border {
width: 2
color: "black"
}
ListView {
id: deviceTreeView
model: deviceTreeModel
delegate: deviceTreeDelegate
highlight: SelectionRectangle {}
anchors.fill: parent
anchors.margins: 6
}
Component {
id: deviceTreeDelegate
Rectangle {
border.color: "#CCCCCC"
width: deviceTree.width
height: 30
smooth: true
radius: 2
MouseArea {
anchors.fill: parent
onClicked: { deviceTreeView.currentIndex = index; window.selectedDeviceChanged(deviceName) }
}
}
}
}
SelectedRectangle.qml
Rectangle
{
id: selectionRectangle
color: "lightsteelblue"
smooth: true
radius: 5
}
SOLUTION: The rectangle in deviceTreeDelegate was by default white and overlapped the selection rectangle. Using the property it's set as trasparent so that the selection can be seen.
This is due to the default Rectangle color being white and the highlight being stacked under the delegate. Setting the Rectangle color to "transparent" will allow the highlight to be visible through the delegate.
Your code gets two mistakes :
The component for the highlight property. The name of the type of the component is the same than the name of the QML file where it is defined. You defined it in a file named SelectedRectangle.qml so you have to write highlight: SelectionRectangle {} in your main QML file
The type of the highlight member is Component. So the component that you use for this member should have got a type which inherits Component. Or you use a QML component that inherits Rectangle and Rectangle does not inherit Component. You should enclose your SelectedRectangle in a Component object, just like you did for the delegate.
Finally, you should write something like this for your highlight component :
highlight: Component {
SelectedRectangle {}
}