How to delete a stackLayout that was is associated with a tabButton in a TabBar - qt

I've created a Qt empty app where the qml code is the below.
What i want to do is i click on the button "add Tab" and create both the tab and the correspondent page. But if i delete (click on the remove Tab) it doesn't get completly removed!
If i click on "add Tab2" button it was supposed to appear the second page.
How can this be solved?
main.qml:
import QtQuick 2.7
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.3
import QtQuick.Window 2.3
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Button{
id:createButton
text:"add Tab"
onClicked: { newTab(1) }
anchors.right: parent.right
anchors.bottom: parent.bottom
}
Button{
text:"remove Tab"
onClicked: { closeTab() }
anchors.right: createButton.left
anchors.bottom: parent.bottom
}
Button{
id:createButton2
text:"add Tab2"
onClicked: { newTab(2) }
anchors.left: parent.left
anchors.bottom: parent.bottom
}
function newTab (val) {
var c = Qt.createComponent("Panel_"+val+".qml")
var tab1 = c.createObject(content)
tabBar.addItem(tabButton.createObject(tabBar, {text: "teste", "font.pixelSize": 14} ))
}
function closeTab(){
var _contentData = tabBar.contentData
for (var i = 0; i < _contentData.length; ++i)
{
if( _contentData[i]['contentItem']['text']==="teste"){
var _removeItem = tabBar.itemAt(i);
tabBar.removeItem(_removeItem);
}
}
tabBar.setCurrentIndex(0)
}
header: TabBar {
id: tabBar
opacity:0.8
}
Component {
id: tabButton
TabButton {
font.pixelSize: 14
}
}
StackLayout {
id: content
currentIndex: tabBar.currentIndex
anchors.fill: parent
}
}
Panel_1.qml
import QtQuick 2.0
Item {
property string title: qsTr("panel1")
Text{text:"panel1"}
}
Panel_2 qml is the same thing as Panel_1.

You have removed the corresponding item from the TabButton but not the item corresponding to StackLayout, so you must remove the child with the same index, but when you are removing an item from a list you must iterate from the end to the beginning.
function closeTab(){
var _contentData = tabBar.contentData
for (var i = _contentData.length -1 ; i >= 0; --i)
{
if( _contentData[i]['contentItem']['text']==="teste"){
var _removeItem = tabBar.itemAt(i);
tabBar.removeItem(_removeItem);
content.children[i].destroy()
}
}
tabBar.setCurrentIndex(0)
}

Related

Pass value from child QtQuck QML to main QML

I have to pass some values from child QML open with component to main QML and use them to do something in main QML.
This is my two QML files:
I have mail.qml like this:
import QtQuick 2.10
import QtQuick.Window 2.10
import QtQuick.Controls 2.3
ApplicationWindow {
id: applicationWindow
property string selected_contact_account_str: String()
/* Contacts */
function createContacts() {
var component = Qt.createComponent("ContactList.qml");
console.log("Component Status:", component.status, component.errorString());
var window = component.createObject(applicationWindow, {"x": 0, "y": 0});
window.showFullScreen();
}
Icon {
id: contacts
anchors.top: parent.top
anchors.topMargin: 60
anchors.left: parent.left
anchors.leftMargin: 20
iconsize: 96
iconsource: "content/contacts_icon.png"
iconname: "Contacts"
fontsize: 14
MouseArea {
anchors.fill: parent
onClicked: createContacts()
}
}
/* End Contacts */
}
And an ContactList.qml with Button:
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Window 2.2
ApplicationWindow {
id: contactsList
Item {
Item {
id: appContainer
anchors.fill: parent
anchors.centerIn: parent
Button {
id: contact_select
text: qsTr("Select")
onClicked: {
// I want to pass value from here to main.qml
// store in selected_contact_account_str
// So I can use it in mail.qml
}
}
}
}
How can I do?
you can use signal and slot to do it.
In
ApplicationWindow
id: contactsList
signal sendmessage(var message)
.
.
.
onClicked: {
contactsList.sendmessage("test");
}
then in first file
function createContacts() {
window.sendmessage.connect(handleMessage)
}
function handleMessage(message){
}

TableView QML Type onClicked event

I am currently using a TableView in my QML file. I would like to know which cell the user clicked.. There is a post here: https://forum.qt.io/topic/84284/tableview-onclicked-slot/2 which shows the onClicked code in the QML file. However, when i tried on my code it says invalid property name. My QML file code is:
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import TransactionHistoryTableModel 1.0
import tech.siotgov.DataManager 1.0
import "../../components" as Components
import "../../utils/httpRequest.js" as HttpRequest
Rectangle {
id: root
objectName: "TransactionHistory"
color: "white"
property string pageTitle: "Transaction History"
ColumnLayout {
id: home
anchors.leftMargin: parent.width * 0.05
anchors.rightMargin: parent.width * 0.05
anchors.fill: parent
anchors.horizontalCenter: parent.horizontalCenter
Components.PageTitle {
title: pageTitle
}
Rectangle {
id: transactionHistoryDisplay
color: "white"
Layout.fillWidth: true
Layout.preferredHeight: parent.height - 100
Components.Table {
model: _transactionHistoryTableModelAPI
columnWidths: [0.4, 0.6]
onClicked: {
console.log(" click ")
console.log(color_string)
}
}
}
Item { //spacer
Layout.fillWidth: true
Layout.fillHeight: true
Rectangle {
anchors.fill: parent
color: "white"
}
}
}
Component.onCompleted: {
const locationId = DataManager.currentLocation.locationId;
const d = new Date()
d.setTime(d.getTime() - d.getTimezoneOffset()*60*1000);
const datetimeStamp = d.toISOString().split('.')[0]
_transactionHistoryTableModelAPI.resetTable(locationId);
HttpRequest.query(
"query { transactionsByLocation(fromDateTime:\"2019-01-01T07:54:34\", toDateTime:\"" + datetimeStamp + "\", location:" + locationId + ") { transactionId, datetime, items { transactionItemId }, transactionType {name}, location_1{locationName}, location_2{locationName} } }",
res => {
_transactionHistoryTableModelAPI.updateTable(res.data.transactionsByLocation);
})
}
}
The Table.qml file is:
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
TableView {
anchors.fill: parent
clip: true
property var columnWidths: [0.5, 0.5] // as fractions of parent width
// preferably overwrite this when using
columnWidthProvider: function (column) { return Math.max(parent.width * columnWidths[column], 1) }
delegate: Rectangle {
implicitHeight: text.implicitHeight
border.color: "#dddddd"
color: (heading==true)?"#dddddd":"white"
Text {
id: text
text: tabledata
width: parent.width
wrapMode: Text.Wrap
padding: 5
}
}
}
In a view you must set the MouseArea in the delegate and expose it through a signal from the root of the component:
Table.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
TableView {
id: root
anchors.fill: parent
clip: true
signal clicked(int row, int column) // <---
property var columnWidths: [0.5, 0.5] // as fractions of parent width
// preferably overwrite this when using
columnWidthProvider: function (column) { return Math.max(parent.width * columnWidths[column], 1) }
delegate: Rectangle {
implicitHeight: text.implicitHeight
border.color: "#dddddd"
color: heading ? "#dddddd" : "white"
Text {
id: text
text: tabledata
width: parent.width
wrapMode: Text.Wrap
padding: 5
}
MouseArea{
anchors.fill: parent
onClicked: root.clicked(model.row, model.column) // <---
}
}
}
*.qml
// ...
Components.Table {
model: _transactionHistoryTableModelAPI
columnWidths: [0.4, 0.6]
onClicked: console.log(row, column)
}
// ...

Qt 5.12 TextArea focus is lost forever

When TextArea is a child of ApplicationWindow with flag set to Qt.Popup, it is not possible to set focus neither by mouse clicking not by calling forceActiveFocus(). Here is the code :
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Controls.Material 2.3
ApplicationWindow {
id : mainWin
visible: true
width: 640
height: 480
title: qsTr("Bug reproduction scenario")
Material.theme: Material.Dark
TextArea {
anchors.centerIn: parent
placeholderText: qsTr("parent text")
}
Button {
id : closeAppBtn
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
text : qsTr("Close app")
onClicked: {
Qt.quit();
}
}
ApplicationWindow {
id : childWin
width : mainWin.width/2
height: mainWin.height/2
visible: false
Material.theme: Material.Dark
x : mainWin.x + width/4
y : mainWin.y + height/4
flags : Qt.Popup
TextArea {
id : childTextArea
anchors.centerIn: parent
placeholderText: qsTr("child text")
}
Button {
id : closeParentWinBtn
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
text : qsTr("Close child win")
onClicked: {
childWin.close();
}
}
}
Button {
text : qsTr("show another window")
anchors.left : closeAppBtn.right
anchors.leftMargin: closeAppBtn.width/2
anchors.top : closeAppBtn.top
onClicked: {
if ( !childWin.visible ) {
childWin.visible = true;
}
}
}
}
It's not possible to set focus to childTextArea neither by mouse clicking nor by setting forceActiveFocus().
The same component is placed on the first window and it's ok to set focus to it. And if you comment out setting flag to Qt.Popup evertyhing is ok.
Is it a known behaviour? What should I do to use TextArea inside ApplicationWindow with PopUp flag?

how to load child1.qml page on to main.qml page calling from another_child.qml page

In my MyHeader.qml cannot load the MyChild2.qml. How to load child qml page on to mmain.qml page calling from another child qml page as shown below.
TestProject Folder
qml Folder
Main.qml
MyChild1.qml
mainui Folder
MyHeader.qml
MyChild2.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
import "."
// Main.qml
ApplicationWindow {
id: rootApp
Loader {
id: loaderPage
anchors.fill: parent
}
MyChild1 {
}
}
// MyChild1.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
import "."
Page {
id: myItem1
anchors.fill: parent
MyHeader {
anchors.top: parent.top
}
}
// MyChild2.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
import "."
Page {
id: myItem2
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#000000"
}
}
// MyHeader.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
import "."
Rectangle {
id: myHeader
width: parent.width
height: dp(30)
color: "lightblue"
Text {
id: loadQML
text: "Load QML"
color: "#000000"
font.pixelSize: dp(20)
MouseArea {
anchors.fill: parent
onClicked: {
myItem1.visible = false
loaderPage.source = "MyChild2.qml"
loaderPage.Top
}
}
}
}
Using the Loader and Connection I am getting Cannot assign to non-existent property "onPageChanged"
import QtQuick 2.10
import "mainui"
ApplicationWindow {
id: rootApp
signal pageChanged(int page);
Loader {
id:rootLoader
anchors.fill: parent
source: "mainui/Page1.qml"
Connections {
target: rootLoader.item
onPageChanged: {
switch(page)
{
case 1: rootLoader.source = "mainui/Page1.qml"; break;
case 2: rootLoader.source = "mainui/Page2.qml"; break;
}
}
}
}
} // APP
Due to scope limitation of Loader you cannot access items outside it. But you can notify the Loader to do some action. In the example below there are 2 components define a signal. The Loader connects this signal to a handler:
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
id: win
width: 400
height: 400
title: "Test"
visible: true
Component {
id: page1
Rectangle {
signal pageChanged(int page);
anchors.fill: parent
color: "orange"
Text {
anchors.centerIn: parent
text: "PAGE 1\nClick to change"
horizontalAlignment: Text.AlignHCenter
}
MouseArea {
anchors.fill: parent
onClicked: {
pageChanged(2);
}
}
}
}
Component {
id: page2
Rectangle {
signal pageChanged(int page);
anchors.fill: parent
color: "lightblue"
Text {
anchors.centerIn: parent
text: "PAGE 2\nClick to change"
horizontalAlignment: Text.AlignHCenter
}
MouseArea {
anchors.fill: parent
onClicked: {
pageChanged(1);
}
}
}
}
Loader {
id: loader
anchors.fill: parent
sourceComponent: page1
Connections {
target: loader.item
onPageChanged: {
switch(page)
{
case 1: loader.sourceComponent = page1; break;
case 2: loader.sourceComponent = page2; break;
}
}
}
}
}

How to implement swipeview QtQuick 2.5

I have QT 5.5 and it won't support SwipeView. I tried doing with listView but I am not getting what I expected. I want a similar functionality code in QT 5.5 like the code given below which is written in QT 5.6. Please help
import QtQuick 2.6
import QtQuick.Controls 2.0
import QtQuick.Window 2.0
Window {
visible: true
width: 200
height: 400
title: qsTr("Hello World")
id: page
SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: 0
Page {
Label {
text: qsTr("First page")
anchors.centerIn: parent
}
}
Page {
Label {
text: qsTr("Second page")
anchors.centerIn: parent
}
}
Page {
Label {
text: qsTr("Third page")
anchors.centerIn: parent
}
}
Page {
Label {
text: qsTr("Fourth page")
anchors.centerIn: parent
}
}
Page {
Label {
text: qsTr("Fifth page")
anchors.centerIn: parent
}
}
}
Rectangle
{
id:minus
width:parent.width/2
height:100
anchors.left:parent.left
anchors.bottom:parent.bottom
color:"red"
MouseArea
{
anchors.fill:parent
onClicked:{
if(swipeView.currentIndex>0)
swipeView.currentIndex--
}
}
}
Rectangle
{
id:plus
width:parent.width/2
height:100
anchors.right:parent.right
anchors.bottom:parent.bottom
color:"green"
MouseArea
{
anchors.fill:parent
onClicked:{
if(swipeView.currentIndex<4)
swipeView.currentIndex++
}
}
}
}
If you cannot update your Qt version, you can indeed approximate a SwipeView using a ListView, a VisualItemModel, and a default qml property.
SwipeView.qml
ListView
{
id: root
// Allow to add pages as you would for a QtQuick.Controls 2 SwipeView
// Each item you declare in your SwipeView will be reparented to itemModel
default property alias items: itemModel.children
// SwipeView is horizontal
orientation: Qt.Horizontal
// Hide out of bounds pages
clip: true
// Do not stop between two pages
snapMode: ListView.SnapToItem
// Update currentIndex as you swipe through the pages
highlightRangeMode: ListView.StrictlyEnforceRange
model: VisualItemModel {
id: itemModel
// Used to bind the pages size to the swipeView size
onChildrenChanged: {
for(var i=0;i<children.length; i++)
{
children[i].width = Qt.binding(function(){return root.width})
children[i].height = Qt.binding(function(){return root.height})
}
}
}
}
Page.qml
Item {
property string title
Rectangle
{
anchors.fill: parent
border.width: 1
}
Text
{
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 20
text: title
}
}
PageIndicator.qml
Row
{
id: root
property int count
property int currentIndex
property Component delegate: bullet
property bool interactive
spacing: 5
Component
{
id: bullet
Rectangle
{
height: 10
width: height
radius: height/2
color:"black"
opacity: currentIndex==index?0.8:0.2
}
}
Repeater
{
model: root.count
Loader
{
property int index: model.index
sourceComponent: delegate
}
}
}
main.qml
import QtQuick 2.5
import QtQuick.Controls 1.4
ApplicationWindow
{
id: window
visible: true
width: 300
height: 300
SwipeView
{
id: swipeView
anchors.fill: parent
Page
{
title: "Page 1"
}
Page
{
title: "Page 2"
}
Page
{
title: "Page 3"
}
}
PageIndicator
{
id: pageIndicator
anchors.bottom: swipeView.bottom
anchors.bottomMargin: 10
anchors.horizontalCenter: swipeView.horizontalCenter
count: swipeView.count
currentIndex: swipeView.currentIndex
}
}
Qt Quick Controls 2 was introduced in Qt 5.7:
Qt Quick Controls 2 provides a set of controls that can be used to build complete interfaces in Qt Quick. The module was introduced in Qt 5.7.
Qt Labs Controls was introduced in Qt 5.6, so the code that you referenced would have to use the Qt.labs.controls 1.0 import in order to run with Qt 5.6.
You need to use a newer Qt version (5.6 or newer).

Resources