I am implementing stackview in my application.
SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: showfooter.currentIndex
DashboardListView{
id:dashboard
}
Settings{
id:setting
}
Cart{
id:cart
}
}
StackView {
id: stackView
initialItem: Pane {
id: pane
}
}
When i am loading some other screen(like SightDescription.qml) from DashboardListView using push method and cliking somewhere on that screen its calling slots for DashboardListView. DashboardListView Screen controls are getting onclick signal. Is there any setting related to stack view that I need to do, I read stackview's documentation but did not find anything to restrict this behavior.
It seems like the Pane is usually intercepting the mouse events, so the lower Items cannot receive them.
When you push the new item on the StackView the Pane becomes visible: false and therefore does not care for input anymore. If the new Item does not handle the mouse events, they will propagate to the lower Item.
To prevent that, you have various options:
Make sure that all Items pushed on the StackView will handle mouse events, e.g. by making a Pane or a MouseArea the root item.
Place a MouseArea directly below the StackView that is only enabled when there are Items on the StackView
Some more... e.g. installing EventFilters in C++ e.t.c. but I think 1 and 2 should be suffice and be easy to implement.
Related
I have many pages and when a button is clicked I make transitions between these pages with a StackView, push and pop. And in these pages when corresponding buttons are clicked I make these buttons red. However, when I pop and re-opened the same page with a push, button is no longer red. So that makes me think that pop and push destroys and creates a new page which is the opposite what is written in docs:
This means that any item pushed onto a StackView will never be
destroyed by the StackView; only items that StackView creates from
Components or URLs are destroyed by the StackView.
Here is the code for stackview:
Window{
id:main
property bool isAbsOffRoad: false
StackView{
id:contentFrame
initialItem:Qt.resolvedUrl("qrc:/MainPage.qml")
Connections{
target:contentFrame.currentItem
onBackButtonPressed:{
contentFrame.pop() }
}}
And then here is how I push:
Item {
id:backgroundItem
LeftButtons{
id:buttonSettings
MultiPointTouchArea{
onPressed{
contentFrame.push("qrc:/SettingsPage.qml")}
}}
I cannot see a reason why the page doesn't preserves it's state when popped and pushed back. What might be the reason?
Another question is: I get a
QML Connections: Cannot assign to non-existent property
"onBackButtonPressed".
However, back buttons work. Why I get that error?
The documentation you quote gives you the answer.
This means that any item pushed onto a StackView will never be destroyed by the StackView; only items that StackView creates from Components ->or URLs<- are destroyed by the StackView.
If a StackView creates an item from a URL, it will have ownership of it, and therefore feel free to destroy it.
Your code shows this:
initialItem:Qt.resolvedUrl("qrc:/MainPage.qml")
So you're giving the StackView a URL to your QML. If you don't want it to do that, try doing something like this instead:
initialItem: MainPage {}
That way, the StackView will be given a fully constructed item, and it won't try to destroy it.
For your second question, I'm guessing that your MainPage.qml does not define that signal. You could create that signal in MainPage just to remove the warning, or you can try adding the ignoreUnknownSignals property to your Connections object.
UPDATE:
You can still use push and pop. You just have to provide a created instance of your item, not just the item type. You could try something like this, for example:
component SomePage: Rectangle {
signal clicked()
MouseArea {
anchors.fill: parent
onClicked: parent.clicked()
}
Component.onCompleted: {
console.log("Created: " + color);
}
Component.onDestruction: {
console.log("Destroyed: " + color);
}
}
SomePage {
id: bluePage
color: "blue"
visible: false
onClicked: contentFrame.push(redPage)
}
SomePage {
id: redPage
color: "red"
visible: false
onClicked: contentFrame.pop();
}
StackView {
id: contentFrame
anchors.fill: parent
initialItem: bluePage
}
I am using Repeater and Delegate to display a list, it all works fine but when i clean the model the GUI does not clean it, still old list is shown. I pass the model from cpp connector to qml.
I have tried update(), repaint() but no avail.
Any leads would be helpful.
Cpp code:
void ModelCpp::clearMessage() {
qDeleteAll(messageList);
messageList.clear();
emit messageListUpdated();
}
QML
ColumnLayout {
spacing: 1
Repeater{
model: modelCpp.messageList
delegate: Rectangle {
visible: true
color: colorBoxShader
Layout.preferredWidth: 100
Layout.preferredHeight: 20
RowLayout{
anchors.fill: parent
Text {
text: modelData.label
Layout.alignment: Qt.AlignLeft
Layout.leftMargin: layoutLeftMargin
color: "white"
font.bold: true
...
```
Edit:
I narrowed down to QStackedWidget, I am using QStackedWidget to load different pages. It was clear on one screen but now I noticed it is happening on all screen. Until the qml page is not current page, it is not updated and has old value. How can I rerender page in background when it is not current page.
I figured out the issue. With QStackedWidget only the visible page is updated/repainted but not the invisible page. When the invisible page becomes visible it is painted and you will see old values briefly before new values are painted. Create new QQuickWidget each time and add it to QStackedWidget.
I'm a C++ developer, now studying about GUI development using QML in QtQuick.
In GUI creation, only one screen is visible to the user.
And based on user interaction, the screens are switched.
But what actually happens behind?
There are lot of info only on how to design a single screen, but very less resource for how to manage the transitions of their states.
Are all the screens and components loaded when starting the application and change the layer order to display once screen,
OR
after an user action, the new screen is built, loaded and old is destroyed ( only one screen is in memory at a time)
What is the term for this type of handling.
It would be so helpful to point to where i can find such information.
If you can't understand my question,please let me know. I will rewrite again!!
There is a convenient ready-made solution available: StackView. It provides built-in transitions for pages that slide/fade in and out.
StackView {
id: stack
initialItem: Page {
Button {
text: "Push"
anchors.centerIn: parent
onClicked: stack.push(Qt.resolvedUrl("OtherPage.qml"))
}
}
}
StackView allows you to push items, URLs and components. When pushing either of the latter two, StackView automatically creates and destroys the instance when appropriate. For example, if you push multiple URLs or components, it will only instantiate the top-most one that becomes the current item on the stack. Once you pop items off the stack, it creates an instance of the item underneath on demand once it becomes the current top-most item on the stack. StackView also allows you to replace one or more items in the stack. When popping or replacing dynamically created items off the stack, it automatically destroys the instances after the respective transitions are finished.
One of the possible options to switch between different screens using states:
ColumnLayout {
id: controls
states: [
State {
id: state1
name: "STATE1"
property list<Item> content: [
Loader {
...
},
MyItem {
...
}
]
PropertyChanges {
target: controls
children: state1.content
}
},
State {
id: state2
name: "STATE2"
property list<Item> content: [
MyHud {
...
}
]
PropertyChanges {
target: controls
children: state2.content
}
}
]
}
You can use Loader to load different qml-files or qml-components.
Example:
import QtQuick 2.0
Item {
width: 200; height: 200
Loader { id: pageLoader }
MouseArea {
anchors.fill: parent
onClicked: pageLoader.source = "Page1.qml"
}
}
I want to create a QML item which disappears when the mouse moves outside of it. Here is my code:
Item {
id: disappearing_element
ListView { ... }
MouseArea {
id: collapser
anchors.fill: parent
propagateComposedEvents: true
hoverEnabled: true
onExited: {
disappearing_element.visible = false
}
}
}
It works well, but MouseArea propagates events like onClicked() onDoubleClicked() only (as said in Qt docs).
Is there a way to notify disappearing_element's childrens about mouse enter and mouse exit events (without using a Popup element)?
I think this is one of the common needs when developing QtQuick apps. One solution we currently use quite often is to add MouseArea in each of the children that need check mouse containment, and emit signals (and catch these signals in your main item) when the mouse enters or exits.
Things go a bit complicated when the children items also need such mechanism to manage their children. However, for common usage, this approach is enough for us right now.
I want to set the activeFocus for a FocusScope by clicking anywhere within an Item.
Is there a way to achieve this without having a MouseArea over the entire Item? Because it would have to overlay all elements within the Item, making them unclickable.
I'm pretty new to QtQuick/QML and have troubles understanding how to properly implement FocusScopes. I've read about propagating click signals, but couldn't get it to work.
Assuming I have something like this (no FocusScopes for readability):
Rectangle
{
id: outerRectangle
width: 1000
height: 1000
// various controls in here
Rectangle
{
id: innerRectangle
anchors.centerIn: parent
width: 200
height: 200
// even more controls in here
}
}
I want the outerRectangle to get the activeFocus when I click anywhere on the outerRectangle and vice-versa for the innerRectangle. But all controls on both Rectangles still have to work properly.
How can I achieve this?
Surround your Item with FocusScope:
FocusScope {
Item {
focus: true
}
}
See Qt Doc