How to change view in Qml? - qt

My program will display pictures in 3 ways: ListView, GridView and PathView. Program will have 3 buttons for each type and when i press button for ListView images are dispayed as list and so on... I can do this with Qml Loader:
Loader { id: pageLoader; anchors.fill: parent; source: "pics/PathLayout.qml"}
and then when i will press button, source will be changed. The problem is that it will download source again and again that is not good.
Another way is to locate views not in separate files, but in main.qml, set visible: false and using states change visible for true. Now problem is that i will instantiate all three views at the start even if i will not change view.
Can I somehow do this, so program starts with GrisView, for example, and it will download another view only if i press button and somehow remember this view so when will need it again, I will not download it again?

You could combine both solutions.
You declare a common model, three loaders (one for each type of view) and three associated buttons. The first time a button is clicked, you active the loader (this way the view is loaded). The next time a button is clicked, you only active/deactivate the visible property of the loaded Component.

It's not clear to me why your images would be downloaded over and over again. The list of images (the actual data) is your model, not your view. That should only occur once. Depending on your needs, that can be done in either C++ or QML. The way you display that model (your view) has nothing to do with that. And there's a million different ways you could display the images. Here's another option:
StackLayout {
currentIndex: 1
ListView {
model: imageList
}
GridView {
model: imageList
}
PathView {
model: imageList
}
}

Related

QML ComboBox not saving selection

I have an issue similar to this post: https://forum.qt.io/topic/88519/editable-combobox-not-saving-edited-text/2
Where after I make a selection in the dropdown, if I scroll out of view and then back into view, the selection reverts back to the previous selection. I have these combo boxes in a scrollable TableView which apparently reloads elements every time they come back into view. Also, my ComboBox is not editable but I just want to be able to save the new selection I make.
I know I need to handle onAccepted, but I am not sure how to save the new value I select into the current selection that gets displayed if I leave the view then come back to it. I have 2 methods like this:
onDisplayTextChanged: {
console.log("currentText in onDisplayTextChanged: " + currentText)
onAccepted()
}
onAccepted: {
console.log("currentText in onAccepted: " + currentText)
}
I use onDisplayTextChanged to receive the new value selected that I can pass to a Python 3 script in the future, before calling onAccepted because onAccepted does not trigger for some reason after I click on a new selection. This is definitely not preferable for me though.

Qml / Qt creator: How to "spawn"/create a custom component multiple times

Trying to make a UI for a program in Qt creator.
I got a scroll view where I want to place a custom component (a rectangle). I can manually put the component in there multiple times and scroll up and down so got that working.
My problem is that I want to generate the component automatically when the user presses a button.
So my question is how to "generate/spawn/create" a custom component into a scroll view when the user presses a button
So far I've tried with loaders and calling the custom component directly inside an onClicked function but this does not seem to work.
var component = Qt.createComponent("CustomComponent.qml");
onClicked: {
component.createObject(column);
I am trying to create the component inside a column with the id column
you can compare what I am trying to achieve with a social media feed. Where I got a list that is scrollable and I want to put components(atm just a rectangle) in the list.
You can use Repeater for that:
Repeater {
id: repeater
model: 0
CustomComponent {}
}
Button {
onClicked: {
repeater.model += 1;
}
}
Repeaters can be used in positioning items(Row, Column, Grid) and layouts.
Also it is possible use a list as a model. So in that case you can reach model data(model[index]) with modelData and index with index in your custom component.

how to force loader to reload / reset or delete the cache of preloaded qml page

In qml i have a page main.qml, if i click on rectangle in that page it opens a component from second.qml file and a listview appears. The listview is very long and can be scrolled down. To go out to the main.qml (previous page) from second.qml it is also done by creating a back button. So far everything is ok and it works and is done by using loader and then changing the loader source.
The problem starts when i revisit the second.qml after clicking again on the rectangle in main.qml. This time it shows the listview left at the last time.
What i want is to reload the second.qml as it loaded it first time. I have came across clear componentcache etc. However, it is not working for me.
A simple example on how to clear the cache memory of loader to reload it like i was loaded first time in qml would be helpful.
in main.qml
MouseArea {
anchors.fill: parent
onClicked: {
pp.close()
//clearComponentCache(loader)
loader.setSource("second.qml",
{ "x":0,
"y":30});
//loader.reload()
}
}
I ran into a similar problem and I found a workaround which worked fine.
(https://forum.qt.io/topic/102523/reload-a-loader-on-button-click/5)
Deactivate loader
Set the source
Activate loader
loader.active = false;
loader.source = "some_file.qml";
loader.active = true;
As said, this is just a workaround and I would really like to know if there is clean way to do this.

How to know that the list items are added successfully in QML listview?

I have created a list of buttons using delegate.
ListView
{
id: list
width: 180; height: 200
delegate: Button
{
width: 180; height: 40
//assigning few properties
}
}
From my .cpp I clear the list and again adding items.
Is there any signal that I can check every time the list is refreshed, and all items are added successfully?
Implement a proper QAbstractListModel, it includes notification for adding and removing list items. So changes will be reflected automatically and in the most efficient manner.
Sounds like you are using a plain QList exposed as a model, that's pretty much wrong, especially when you have a dynamic and changing model. You can still force update by exposing the list as a Q_PROPERTY with a NOTIFY signal, but that will be wildly inefficient, as it will cause all delegates to be recreated for every change, rather than efficiently reflecting changes only.
you can add handler to your button
Component.onCompleted: console.log("button is created")
to make sure that button is being constructed

QML Webview renders SELECT elements with x-offset

I’m currently implementing a WebView which contains a web page with a select form element on the page. Whenever I click on the select box, the dialog containing the possible values is appearing off the page.
The dialog doesn’t centre itself within the WebView or the parent. On the simulator it appears just below the dropdown box on the web page but is too wide to fit on the screen (Obscuring the scrollbar) and on the device it appears in the bottom left hand corner of the screen.
Has anyone got any experience with this? I’m simply using the QML WebView item and it’s not within a Flickable (Which I originally thought would be the issue)
Background and Investigation
Two approaches to rendering this page:
A simple project which uses the Qt QWebview, and running on the simulator gives this:
Note: the select menu is the full width of the window.
With a simple project that uses the following QML:
import QtQuick 1.0
import QtWebKit 1.0
Rectangle {
anchors.fill: parent
WebView {
anchors.fill: parent
url: "http://www.w3schools.com/tags/tryit.asp?filename=tryhtml_option"
}
}
would yield the following results:
What am I doing wrong here? What do I need to do to my QML to make it render the menus properly?
Ok. This feels wrong.
I can't believe there's a story on my board which is "As a Qt user, I can select values from a long list".
So my solution to this was inject a chunk of Javascript into the Webview using evaluateJavascript which crawls the DOM looking for SELECT elements.
When the select is clicked, then call out to QML with the list of options, and then render a QML version of the select box.
The return trip is simpler, but just as unappealing.
I tried added a click or tap listener to the select elements, but the DOM API isn't complete (will try and find a canonical link), and nothing I tried would trigger the handler. In the end, I hid it, and added inserted a button in its place.
There has to be a better way.

Resources