How to push different view to stack view using a function in qml main file - qt

working on an application using qml for the interface. I have a stack view in the main qml file which will push the qml file which will be a page to the stack view. Because there are multiple pages and buttons in these pages that when clicked may push a different page onto the stack view, I created a function in the main qml file which i will call from the pages when buttons are clicke. The pages folder which contain many different pages is a subdirectory of main.qml folder. The functionis supposed to push the pages unto the stack view. However, on click of the button, the satck view does not push the new page.
This is the code below
main qml file
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import "pages"
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
property url source: ""
function changeView(source){
stackView.push(Qt.resolvedUrl(source))
}
Rectangle {
id: rectangle
color: "#391199"
anchors.fill: parent
StackView {
id: stackView
anchors.fill: parent
initialItem: Qt.resolvedUrl("pages/homepage.qml")
}
}
}
/*##^##
Designer {
D{i:0;formeditorZoom:0.75}
}
##^##*/
homePage.qml
import QtQuick 2.0
import QtQuick.Controls 2.15
import "qrc:../main.qml" as Main
Item {
Rectangle {
id: rectangle
color: "#08630f"
anchors.fill: parent
Button {
id: button
x: 478
y: 255
text: qsTr("Change ")
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: 10
anchors.bottomMargin: 10
onClicked: {
source = "pages/nextPage.qml"
Main.changeView(source)
}
}
}
}
nextPage.qml
import QtQuick 2.0
import QtQuick.Controls 2.15
import "../main.qml" as Main
Item {
Rectangle {
id: rectangle
color: "#08404b"
anchors.fill: parent
Button {
id: button
x: 478
y: 255
text: qsTr("Change ")
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: 10
anchors.bottomMargin: 10
onClicked: {
Main.changeView("pages/homePage.qml")
}
}
}
}
I suspect the problem is coming from the calling of the function but i have a little expertise in qml. I get this error: Property 'changeView' of object [object Object] is not a function

You will want to call the changeView function on the actual main window, not on the import.
This involves a bit of "magic", you can give the main Window an id, which will be available in all the children of it (so, magic because if looking at a single page file, you can wonder what that id is doing there). So, make sure to pick a wise name which won't collide with other id (i.e. root would be quite bad)
//main.qml
Window {
id: main_window
function changeView(source) { ... }
}
//homePage.qml
Item {
...
Button {
...
onClicked: main_window.changeView("pages/nextPage.qml")
}
}

Related

QML: Accept TextField onClicked outside

Imagine the following:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
TextField {
anchors.centerIn: parent
onEditingFinished: console.log("input is: " + text)
}
}
How do I achive that the input of the TextField is accepted (onEditingFinished emitted), on clicking anywhere outside of the TextField (not pressing enter, tab,.. just a mouse click)?
I might set a MouseArea around it with onClicked: forceActiveFocus() to force onEditingFinished, but how do I achive this within a large application with many layers/views? This does not seem to be the right solution.
You can take this approach:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
id: root
width: 640
height: 480
visible: true
title: qsTr("Hello World")
MouseArea {
anchors.fill: parent
onClicked: {
if (root.activeFocusItem != null) {
root.activeFocusItem.focus = false;
}
}
}
TextField {
anchors.centerIn: parent
onEditingFinished: console.log("input is: " + text)
}
}
This places a single MouseArea filling your Window as a backstop to anything that might appear above it. Either a mouse click will be accepted by a control sitting above the mouse area or will pass through to it and clear focus on anything that might have it.

Why does my SwipeView page not change when I change the Tab in the TabBar in QML?

So, I'm trying to create a traditional look for my QML application which simply consists of a TabBar and a SwipeView. There's also another component which essentially boils down to a button click which should result in a new tab in the TabBar and a new page in the SwipeView. This works, except that when I click on the previous tab (there's a static tab and page when the app starts up), the page in the view doesn't change.
Here's my QML file -
import QtQuick 2.12
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.12
import QtQuick.Controls 2.13
ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
Component {
id: tabButton
TabButton {
width: implicitWidth
}
}
Component {
id: resultListView
Rectangle {
anchors.fill: parent
color: "green"
}
}
SwipeView {
id: tabBarLayout
Layout.fillHeight: true
Layout.fillWidth: true
interactive: false
currentIndex: 0
LogArea {
id: logArea
}
}
TabBar {
id: tabBar
currentIndex: tabBarLayout.currentIndex
Layout.fillWidth: true
font.capitalization: Font.MixedCase
TabButton {
text: qsTr("log")
width: implicitWidth
}
Connections {
target: qmlBridge
onLoadResultTab: {
tabBar.addItem(tabButton.createObject(tabBar, {text: qsTr("search - " + term)}))
tabBarLayout.addItem(resultListView.createObject())
tabBarLayout.incrementCurrentIndex()
console.log("Added new item...")
}
}
}
}
The onLoadResultTab signal is invoked when the button is clicked. As you can see, I'm adding a new TabButton and incrementing the current index and then creating another component which is just a simple Rectangle for now. Now, when I click on the "log" button, the SwipeView doesn't change its page to the one corresponding to the log tab. Could anyone point out what's the issue here?

How should I start QML files?

I have 4 QML files: MainMenu.qml, AppArea.qml, Result.qml and main.qml.
When my app starts, I want to see first page as MainMenu.qml fullscreen. There is a button (on MainMenu.qml) to start AppArea.qml. When I click the the button, I want to start AppArea.qml as fullscreen new window.
There is a button (on AppArea.qml), when I click that button, I want to show Result.qml but I want to see Result.qml on AppArea.qml, I mean when Result.qml come outs, AppArea.qml will not disappear but Result.qml will appear on AppArea.qml.
There is a button on Result.qml. When I click the button, the Repeater in AppArea.qml will regenerate, because maybe model of Repeater changing like 1, 2, 3, 4.... There is a button on AppArea.qml, when I click the button, I want to open MainMenu.qml as a fullscreen new window like AppArea.qml.
Actually you can think basic: My app is a game like this:
How way should I choose for these jobs?
In addition to the mentioned post, in your case you are using the component from qml file, so you need to load the component first, your main.qml can be like this:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window {
id: mainWindow
title: "Main window"
visible: true
flags: Qt.Dialog
modality: Qt.ApplicationModal
Loader{
id: mainMenuLoader
}
Component.onCompleted: {
mainMenuLoader.source="mainMenu.qml"
var mainMenu = mainMenuLoader.item.createObject(mainWindow);
mainWindow.hide()
}
}
and your mainMenu.qml can look like this:
import QtQuick 2.9
import QtQuick.Window 2.3
import QtQuick.Controls 2.2
Component {
id: mainMenu
Window {
id:mmenu
title: "Main Menu"
width: 600
height: 600
visible: true
flags: Qt.Dialog
modality: Qt.ApplicationModal
Loader{
id: appAreaLoader
}
Text {
text: "This is mainMenu"
}
Button{
id: loadAppArea
anchors.centerIn: parent
text: "Start Game"
onClicked: {
appAreaLoader.source="appArea.qml"
var appArea = appAreaLoader.item.createObject(mainMenu);
hide()
}
}
}
}
you will need to do the same for successive windows ...etc.
While for result, you need to use a MouseArea:
appArea.qml:
Component {
id: appMenu
Window {
id:appMenuWindow
title: "App Menu"
width: 600
height: 600
visible: true
flags: Qt.Dialog
modality: Qt.ApplicationModal
Loader{
id:anotherLoader
visible: true
anchors.left: appMenuText.left
anchors.top: appMenuText.bottom
width: parent.width/3
height: parent.height/3
}
Text {
id: appMenuText
text: "This is App Area"
anchors.centerIn: parent
}
Button{
id: loadResult
text: "Show Result"
onClicked: {
anotherLoader.source = "result.qml"
anotherLoader.visible=true
}
}
Button{
anchors.right: parent.right
id: loadMainMenu
text: "Open main Menu"
onClicked: {
hide()
//mmenu.show()
anotherLoader.setSource("main.qml")
}
}
}
}
result.qml:
Rectangle{
color: "green"
Text {
anchors.centerIn: parent
id: resultxt
text: qsTr("This is result, Click to close")
}
MouseArea {
anchors.fill: parent
onClicked: { anotherLoader.visible = false
}
}
}

How to use mouseclick area from loaded Form in qml?

below is my code snippet where i'm loading qml ui using dynamic object creation method now i have to implement mousearea which reside in loaded file, can anyone help me to do this
Qt.createQmlObject(" import QtQuick 2.0
Loader {
id: pageLoader
source: '/HomeScreenForm.ui.qml'
anchors.fill: parent
anchors.rightMargin: 0
anchors.leftMargin: 0
anchors.bottomMargin: parent
anchors.topMargin: parent
}
", rectangle7)
Create custom item contains MouseArea. To make the area accessible from outside you can use alias, for example:
MyItem.qml
import QtQuick 2.7
Rectangle {
id: root
color: "yellow"
property alias area: mouseArea
MouseArea {
id: mouseArea
anchors.fill: parent
}
Text {
anchors.centerIn: parent
text: "Click me!"
}
}
And then you can create it dynamically:
import QtQuick 2.7
import QtQuick.Window 2.0
Window {
id: mainWindow
width: 600
height: 600
visible: true
Component.onCompleted: {
var component = Qt.createComponent("MyItem.qml");
if (component.status === Component.Ready) {
var obj = component.createObject(mainWindow);
obj.width = 200;
obj.height = 200;
obj.anchors.centerIn = mainWindow.contentItem;
obj.area.onPressed.connect(
function(mouse){
console.log("pressed at (", mouse.x,",",mouse.y,")")
});
}
}
}
Another way is using Connections, as #derM already noticed.

How to use QtQuick.Window element in Qt5 and QML?

I recently installed the Qt5 RC2 for Mac OS X and started developing some QML applications. After looking at the new elements, I especially wanted to try the Window and Screen Element. (http://qt-project.org/doc/qt-5.0/qtquick/qmlmodule-qtquick-window2-qtquick-window-2.html)
So I set the imports at the top of the file like this:
import QtQuick 2.0
import QtQuick.Window 2.0
The import is found, but I can use neither Window nor Screen. Everytime I type Screen or Window an error appears which says "Unknown component (M300)"
Has anyone an idea what the problem is?
Sometimes QtCreator doesn't recognize some types/properties, mainly the ones that were not present in Qt4.x, but that doesn't mean you can't use them, so yes, 'Window' is unknown just like properties 'antialiasing', 'fontSizeMode' or 'active' are, but you can use them, here is an example of use for QtQuick.Window 2.0 :
import QtQuick 2.0
import QtQuick.Window 2.0
Window {
id: win1;
width: 320;
height: 240;
visible: true;
color: "yellow";
title: "First Window";
Text {
anchors.centerIn: parent;
text: "First Window";
Text {
id: statusText;
text: "second window is " + (win2.visible ? "visible" : "invisible");
anchors.top: parent.bottom;
anchors.horizontalCenter: parent.horizontalCenter;
}
}
MouseArea {
anchors.fill: parent;
onClicked: { win2.visible = !win2.visible; }
}
Window {
id: win2;
width: win1.width;
height: win1.height;
x: win1.x + win1.width;
y: win1.y;
color: "green";
title: "Second Window";
Rectangle {
anchors.fill: parent
anchors.margins: 10
Text {
anchors.centerIn: parent
text: "Second Window"
}
}
}
}
You just need to have a Window item as root object, and you can embed other Window items into it.

Resources