Qt.labs.controls: TabButtons don't click - qt

I use Qt 5.6 labs controls. I use TabBar and SwipeView. But TabButtons don't click. I want to paint background of the Item control and so I use Rectangle but the rectangle is fill all screen. My app and I want this: IMAGE.
And my code is this:
import QtQuick 2.6
import Qt.labs.controls 1.0
Rectangle {
TabBar {
id: tabbar
width: parent.width
currentIndex: view.currentIndex
TabButton {
text: qsTr("1")
}
TabButton {
text: qsTr("2")
}
TabButton {
text: qsTr("3")
}
}
SwipeView {
id: view
anchors.fill: parent
currentIndex: tabbar.currentIndex
Item {
id: tab0
Rectangle {
color: "red"
}
}
Item {
id: tab1
Rectangle {
anchors.fill: parent // -> This command is fill all screen so I don't click TabButtons.
color: "blue"
}
}
Item {
id: tab2
Rectangle {
anchors.fill: parent
color: "lightblue"
}
}
}
}
Thanks.

You made the SwipeView fill its parent, but the TabBar has the same parent and occupies some of the same space. SwipeView is an interactive control, so it accepts mouse events. The SwipeView is also declared after the TabBar, which means it has a higher stacking/Z order. These two things combined mean that TabBar is never going to get mouse events.
You can ensure that both have enough space by using ColumnLayout, for example:
import QtQuick 2.6
import QtQuick.Layouts 1.1
import QtQuick.Window 2.0
import Qt.labs.controls 1.0
Window {
visible: true
Rectangle {
anchors.fill: parent
ColumnLayout {
anchors.fill: parent
spacing: 0
TabBar {
id: tabbar
Layout.fillWidth: true
currentIndex: view.currentIndex
TabButton {
text: qsTr("1")
}
TabButton {
text: qsTr("2")
}
TabButton {
text: qsTr("3")
}
}
SwipeView {
id: view
Layout.fillWidth: true
Layout.fillHeight: true
currentIndex: tabbar.currentIndex
Item {
id: tab0
Rectangle {
color: "red"
}
}
Item {
id: tab1
Rectangle {
anchors.fill: parent // -> This command is fill all screen so I don't click TabButtons.
color: "blue"
}
}
Item {
id: tab2
Rectangle {
anchors.fill: parent
color: "lightblue"
}
}
}
}
}
}

Related

How to update or read TextFiled inside GridLayout which is in TabView

I have below stack of components and I want to read and set value of the TextFiled:
-Rectangle
-----TabView
---------Tab
-----------Rectangle
--------------GridLayout
------------------Rectangle
--------------------TextField <--- I want to access this TextField
I have also a case where I need to access Repeater inside the Tab:
-Rectangle
-----TabView
---------Tab
-----------Rectangle
--------------GridLayout
------------------Repeater
--------------------TextField <--- I want to access this TextField also
I have tried to access it using:
var tab0 = myTabView.getTab(0);
tab0.children[0].text = "Some Text"; // I get Undefined Error
I have tried to access the component using a function inside the Tab:
import QtQuick 2.0
import QtQuick.Controls 2.14 as QQC2
import QtQuick.Layouts 1.14
import QtQuick.Controls 1.4 as QQC1
QQC2.Item {
QQC1.TabView {
QQC1.Tab {
title: "tab1"
function printValue () {
console.log("myTextFld.txt: "+myTextFld.txt); // <-- Getting Error myTextFld undefined.
}
Rectangle {
id: tabHolderRext
color: "blue"
GridLayout {
id: myGrid
model: 7
Repeater {
id: herderRepeater
model: header
delegate: Rectangle {
TextField {
// I want to Access This TextField also
}
}
}
Rectangle {
id: row0Rect
Layout.row: 0
Layout.column: index
TextFiled {
id: myTextFld
text: modelData
}
}
// Rest of the rows
}
}
}
}
}
Item id can be used to access the values from TextField if you have all items in same qml file. If you have different qml files then make use of alias types link to access the values.
Repeater case: The Textfield has to update the underlying modelview --> model first then we can make use of the model's data.
Here is a sample code. I have stacked all item's in the same qml file so that access by id works here.
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window {
visible: true
width: 640
height: 480
Item {
anchors.fill: parent
anchors.margins: 10
TabView {
anchors.fill: parent
Tab {
title: "TextField"
Item {
anchors.fill: parent
Grid {
spacing: 20
anchors.fill: parent
anchors.margins: 10
Rectangle {
height: 40
width: 150
TextField {
id: inputId
anchors.fill: parent
placeholderText: "enter text"
}
}
Button {
height: 40
width: 150
text: "show txt"
onClicked: labelId.text = inputId.text
}
Rectangle {
height: 40
width: 150
Label {
id: labelId
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
}
}
Tab {
title: "Repeater"
Item {
anchors.fill: parent
Grid {
spacing: 20
anchors.fill: parent
anchors.margins: 10
columns: 3
ListModel {
id: fruitModel
ListElement { name: "Apple" }
ListElement { name: "Orange" }
ListElement { name: "Banana" }
}
Repeater {
width: parent.width
height: parent.height / 2
model: fruitModel
delegate: Rectangle {
height: 40
width: 150
TextField {
anchors.fill: parent
text: name
onTextChanged: fruitModel.setProperty(index, "name", text) // update model data
}
}
}
Repeater {
width: parent.width
height: parent.height / 2
model: fruitModel
delegate: Rectangle {
height: 40
width: 150
Label {
text: name
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
}
}
}
}
}
}

QML ListView contentHeight property value is incorrect

I have a QML page with a GridLayout that contains the page title, ListView and close button:
GridLayout {
columns: 1
rows: 5
anchors.fill: parent
<page title item>....
ListView
{
id: list
spacing: 15
model: logModel
Layout.fillWidth: true
Layout.fillHeight: true
delegate: Item {
implicitWidth: parent.width
implicitHeight: grid.height
RowLayout
{
id: grid
spacing: 0
width: parent.width
height: commentLabel.implicitHeight
<icon>....
Label {
id: commentLabel
Layout.fillWidth: true
text: comment
wrapMode: Label.Wrap
}
}
}
ScrollIndicator.vertical: ScrollIndicator { }
}
<close button>...
}
Component.onCompleted:
{
console.log("list.contentHeight = ", list.contentHeight, "list.height = ", list.height)
}
when I bind ListView to a model (logModel) that contains items with comment property that contains relatively long multiline text and check contentHeight property of ListView from Component.onCompleted I get the value 161 that is obviously too small (actually it should be greater than 500, because ListView height property value is 461 and it is not enough for all the items).
So I cannot figure out what this 161 is. The only guess is that it is something close to the content height with single-line items (not multiline), but it is not clear what is the logic behind that.
My QT version is 5.13.2.
EDIT1:
The full source code:
ChangeLogPage.qml:
import QtQuick 2.7
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Controls.Styles 1.4
Page
{
id: root
property alias model: list.model
background: Rectangle {
color: "transparent"
}
function close()
{
stack.pop()
}
SystemPalette {
id: palette
}
GroupBox
{
id: box
background: Rectangle {
color: palette.base
}
anchors.margins: 15
anchors.fill: parent
GridLayout {
columns: 1
rows: 5
anchors.fill: parent
ListView
{
id: list
Layout.fillWidth: true
Layout.fillHeight: true
//It is not clear why, but there is an enough left margin.
Layout.leftMargin: 0
Layout.rightMargin: 0
Layout.topMargin: 15
Layout.bottomMargin: 20
//Looks like it is only vertical spacing.
spacing: 15
clip: true
delegate: Item {
width: parent.width
height: grid.height
RowLayout
{
id: grid
spacing: 0
width: parent.width
//height: commentLabel.height
Label {
//id: commentLabel
Layout.fillWidth: true
text: comment //qsTr(comment)
wrapMode: Label.Wrap
}
}
}
ScrollIndicator.vertical: ScrollIndicator { }
}
Button {
Layout.alignment: Qt.AlignRight
text: qsTr("Close")
onClicked: close()
}
}
}
Component.onCompleted:
{
console.log("list.contentHeight = ", list.contentHeight, "list.height = ", list.height)
}
}
main.qml:
import QtQuick 2.7
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2
import LinesGame 1.0
ApplicationWindow {
id: window
visible: true
width: 360
height: 640
title: "Test"
Component {
id: listModelComponent
ListModel {
id: model
}
}
StackView
{
anchors.fill: parent
id: stack
}
function showChangeLogPage(beginIndex, endIndex)
{
if (beginIndex < endIndex)
{
//var component = Qt.createComponent("ChangeLogModel.qml")
//var logModel = component.createObject(this)
var logModel = listModelComponent.createObject(this);
for (var i = beginIndex; i < endIndex; i++)
{
//i.toString()
logModel.append({comment: qsTr("The advertising was added, but it is shown only when you start a new game or load a saved game. Support the developers, tap on the advertising!")})
}
stack.push(Qt.resolvedUrl("ChangeLogPage.qml"), {model: logModel})
}
}
Component.onCompleted:
{
showChangeLogPage(0, 5)
}
}

How to make the listview align better?

My program consisted of a tabbar and stackLayout. I face a layout problem that the tab button is too close to the head of the listview as shown below. They are horizontally aligned together.
But I want the listview to be under the tab button. I tried adding the topMargin in the listview, but it doesn't have any effect at all. Please help.
The code:
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtMultimedia 5.8
import QtQuick.Layouts 1.3
import com.contentplayermod.filemodel 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Tabs")
property int idx: 0
property bool isActive: true
TabBar {
id: bar
width: parent.width
TabButton {
text: qsTr("Main")
}
TabButton {
text: qsTr("View")
}
}
StackLayout {
id: stackLayout
height:parent.height
width: parent.width
currentIndex: bar.currentIndex
Item {
id: mainTab
anchors {
topMargin:60
}
width: 500
height:800
ListView {
id: lv
anchors.margins: 50
width: 200; height: 400
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
focus: true
currentIndex: 0
Component {
id: fileDelegate
Text {
text: fileName
font.pointSize: 20
anchors {
topMargin:60
}
MouseArea{
anchors.fill: parent
}
}
}
model: FileModel{
id: myModel
folder: "c:\\folder"
nameFilters: ["*.mp4","*.jpg"]
}
delegate: fileDelegate
highlightFollowsCurrentItem: true
}
}
Item {
id: viewTab
width: 500
height:800
}
}
}
You can either anchors your stack-top to the bottom of the tab bar like this :
...
StackLayout {
id: stackLayout
height:parent.height - bar.height
anchors.top: bar.bottom
width: parent.width
...
Or much simpler, put everything in a ColumnLayout :
ColumnLayout {
anchors.fill: parent
TabBar {
id: bar
Layout.fillWidth: true
...
}
StackLayout {
id: stackLayout
Layout.fillHeight: true
Layout.fillWidth: true
...
}
}
So you don't have to deal with width and height, and it's more easy to insert new widgets in your window.
You can add spacing to the ColumnLayout to put some space between the TabBar and the content. Or manage this inside the Items displayed by the StackLayout for more flexibility.

Adding Items to a layout of a custom component

I have a custom Footer Component which I would like to reuse in different place in my QML App:
Rectangle {
color: "gold"
height: 50
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
}
RowLayout {
anchors.fill: parent
anchors.margins: 10
Button {
text: "quit"
}
}
}
The use of this is easy:
Window {
visible: true
Footer {
}
}
But now I would like to add a "ButtonA" to the RowLayout of my Footer in one view and a "ButtonB" in another view.
How can I achieve that?
See this answer.
You have to declare a default property in Footer.qml:
import QtQuick 2.0
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
Rectangle {
color: "gold"
height: 50
default property alias content: rowLayout.children
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
}
RowLayout {
id: rowLayout
anchors.fill: parent
anchors.margins: 10
Button {
text: "quit"
}
}
}
This ensures that any items declared as children of Footer instances will be added to its RowLayout.
main.qml:
import QtQuick 2.4
import QtQuick.Controls 1.3
ApplicationWindow {
width: 640
height: 480
visible: true
StackView {
id: stackView
anchors.fill: parent
initialItem: viewAComponent
}
Component {
id: viewAComponent
Rectangle {
id: viewA
color: "salmon"
Footer {
id: footerA
Button {
text: "Go to next view"
onClicked: stackView.push(viewBComponent)
}
}
}
}
Component {
id: viewBComponent
Rectangle {
id: viewB
color: "lightblue"
Footer {
id: footerB
Button {
text: "Go to previous view"
onClicked: stackView.pop()
}
}
}
}
}
I used StackView as a convenient way of navigating between the views.

QT 5.3 / QML: Resizable StackView depending on currentItem

I'm working on a QML StackView that starts with a list of items to select from. Once selected I want to transition _.push(...) to a input form which has larger dimensions than the initialItem.
The only way I have trial-and-errored my way into a situation that works is by making the form Item a nested borderless window.
Q1. A nested window can't be the right type of concept to use for this... right ? there must be another way to do it. What is the right way ?
Q2. My goal after this is to have a transition animation that grows or shrinks between stacks of different sizes. Advice that doesn't preclude that would be best.
code
Main.qml :
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
ApplicationWindow {
property int itemHeight: 30
property int cornerRadius : 5
visible: true
color: "transparent"
flags: Qt.FramelessWindowHint
ListModel {
id: searchFacets
ListElement {
title: "Topics"
page: "content/TopicSearch.qml"
}
// ListElement {
// title: "Domains"
// }
}
StackView {
id: stackView
focus: true
initialItem: SearchFacets {
id: facets
}
delegate: StackViewDelegate {
pushTransition: StackViewTransition {
PropertyAnimation {
target: enterItem
property: "opacity"
from: 0
to: 1
}
}
}
}
}
Initial Item:
import QtQuick 2.3
Item {
height : listView.count * itemHeight
ListView {
id: listView
model: searchFacets
anchors.fill: parent
focus: true
highlightFollowsCurrentItem: false
highlight: Rectangle {
width: parent.width
height: itemHeight
radius : cornerRadius
color: "green"
opacity: 0.5
z:2
x: listView.currentItem.x;
y: listView.currentItem.y
Behavior on y {
SpringAnimation {
spring: 60
damping: 1.0
}
}
}
delegate: Component {
Item {
width: parent.width
height : itemHeight
Rectangle {
anchors.fill: parent
color: "#212126"
radius: cornerRadius
z:0
border.width: 2
border.color : "white"
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
console.log("clicked index: " + index)
listView.currentIndex = index
// listView.forceActiveFocus()
stackView.push(Qt.resolvedUrl(page))
}
}
Text {
text: title
font.pixelSize: 24
font.bold: true
z:1
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
color: "white"
antialiasing: true
}
}
}
}
}
Input Form:
import QtQuick 2.3
import QtQuick.Window 2.0
Item {
Window {
width: 400
height: 400
visible: true
flags: Qt.FramelessWindowHint
Rectangle {
anchors.fill: parent
visible: true
color: "red"
}
}
}
One possible solution is to update the size of the dimensions of the StackView in the click handler that causes the transition. I do not know if that causes any problems with animating the transition.
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
console.log("clicked index: " + index)
listView.currentIndex = index
var component = Qt.createComponent(page)
var res = component.createObject(stackView)
stackView.height = res.height
stackView.width = res.width
stackView.push(res)
}
}

Resources