QT5.12.3 SwipeView enum Forms [duplicate] - qt

This question already has answers here:
How can we declare enumerations in QML, without any JavaScript?
(4 answers)
Closed 3 years ago.
Hi i want to add enum to identify my forms for the SwipeView.currentIndex... But my enum can't be found.
import QtQuick 2.12
import QtQuick.Controls 2.5
ApplicationWindow {
id: window
visible: true
width: 640
height: 480
enum FormsEnum
{
InitForm=0,
MainMenuForm=1
}
SwipeView {
id: swipeView
anchors.fill: parent
currentIndex:FormsEnum.MainMenuForm
Init {
id: init
}
MainMenu {
id: mainMenu
}
}
}
Can anybody help me ????

In order to make it work you have to create a new qml for example Forms.qml:
import QtQuick 2.0
Item {
enum FormsEnum
{
InitForm=0,
MainMenuForm=1
}
}
Then on your qml, you can use:
currentIndex: Forms.FormsEnum.MainMenuForm

Related

Load SwipeView pages dynamically

I have created the following MWE (Qt 5.13.0):
import QtQuick 2.0
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
ApplicationWindow
{
property int itemsNo: 3;
id: window
visible: true
width: 480
height: 480
SwipeView
{
anchors.fill: parent;
id: theSwipeView;
Loader
{
sourceComponent: theSingleComp;
Component
{
id: theSingleComp;
Page
{
Text
{
text: "The single one";
}
}
}
}
Repeater
{
model: itemsNo;
Loader
{
sourceComponent: theMultiComp;
Component
{
id: theMultiComp;
Page
{
Text
{
text: "The multi one " +
(theSwipeView.currentIndex - 1);
}
}
}
}
}
}
}
In my program, I have an unique component (theSingleComp) and multiple components behind him (theMultiComp). As for now, I need to implement the following functionality:
In case the model used for theMultiComp has only 1 item, display only this item and not the theSingleComp. In case the are more theMultiComp items, display it like now. It seems to me that there is no possibility for this to work if I keep the items defined statically. But on the other hand, I don't know how to do this dynamically, since there is a case in which one of the components should not be displayed at all. I tried an approach like this:
sourceComponent: (itemsNo > 1) ? theSingleComp : null;
But then the page for this null component is still created.
Your problem is that Loader is an Item and SwipeView creates a page for it even if it doesn't have a source component.
To solve this problem you can use Repeater instead with a model of 1 (or 0 to disable it). Repeater is also an Item but it has some special code under the hood to be ignored by containers.
import QtQuick 2.0
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
ApplicationWindow
{
id: window
property int itemsNo: 0
visible: true
width: 480
height: 480
SwipeView {
id: theSwipeView
anchors.fill: parent
Repeater {
model: window.itemsNo > 1 ? 1 : 0
Page {
Text {
text: "The single one"
}
}
}
Repeater {
model: window.itemsNo
Page {
Text {
text: "The multi one " + model.index
}
}
}
}
}
(I've simplified your code to remove the explicit Components and the Loaders)
I have come up with the following solution but I am not happy with it. It's very hacky and the user can see how the page index changes.
import QtQuick 2.0
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
ApplicationWindow
{
property int itemsNo: 2;
id: window
visible: true
width: 480
height: 480
SwipeView
{
anchors.fill: parent;
id: theSwipeView;
Component.onCompleted:
{
if (itemsNo > 1)
insertItem(0, theSingleComp);
set0IndexTimer.start();
}
Timer
{
id: set0IndexTimer;
interval: 1;
running: false;
repeat: false;
onTriggered: theSwipeView.setCurrentIndex(0);
}
onCurrentIndexChanged: console.log("page: ", currentIndex);
Repeater
{
model: itemsNo;
Loader
{
sourceComponent: theMultiComp;
Component
{
id: theMultiComp;
Page
{
Text
{
text: "The multi one " + theSwipeView.currentIndex;
}
}
}
}
}
}
Item
{
id: theSingleComp;
Page
{
Text
{
text: "The single one";
}
}
}
}
I am still seeking some other examples.

Instantiating a "native" QML type dynamically

Is it possible to pick between different types of sub-components dynamically (during instantiation)?
For example, some pseudocode (using Qt 5.9):
//MyComp.qml
import QtQuick 2.9
import QtQuick.Layouts 1.3
Item {
property bool useLayout: true
//Here I want to allow the user to choose
//whether a ColumnLayout or Column is used
//(e.g., by means of the useLayout property)
ColumnLayout { //Or Column
...
}
...
}
//main.qml
import QtQuick 2.9
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.9
ApplicationWindow {
width: 640
height: 480
...
MyComp {
id: a
useLayout: false
...
}
}
I don't think there is a way to do exactly what you want, without a lot of javascript. The cleanest way to do this, that I can think of would be the following.
You could make the ColumnLayout invisible and set the Column as the parent of its children with something like this:
//MyComp.qml
import QtQuick 2.9
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.5
Item {
property bool useLayout: true
ColumnLayout {
id: columnLayout
visible: useLayout
Component.onCompleted: {
if (!useLayout) {
butt1.parent = column;
butt2.parent = column;
butt3.parent = column;
}
}
Button {
id: butt1
text: "butt 1"
}
Button {
id: butt2
text: "butt 2"
}
Button {
id: butt3
text: "butt 3"
}
}
Column {
id: column
visible: !useLayout
}
}

How to set an item property of one qml from main.qml

I waste my time to find how set the visible property to false, the delegate being in an another qml file.
For instance here is a simple example based on Places Map.
Marker.qml
import QtQuick 2.0
import QtLocation 5.6
MapQuickItem {
id: idPointsMarker
sourceItem: Loader{sourceComponent: idRect}
visible: true //if set manually to false, everything works correctly
Component{
id: idRect
Rectangle{
width: 20
height: 20
color: "blue"
}
}
}
and the main.qml
import QtQuick 2.0
import QtQuick.Window 2.0
import QtLocation 5.6
import QtPositioning 5.6
Window {
width: 512
height: 512
visible: true
PositionSource {
...
}
property variant locationOslo: QtPositioning.coordinate( 59.93, 10.76)
PlaceSearchModel {
...
}
Map {
id: map
anchors.fill: parent
plugin: Plugin {name: "osm"}
center: locationOslo
zoomLevel: 13
MouseArea {
id : mouseMap
anchors.fill: parent
onDoubleClicked: {
console.log("DoubleClicked")
Marker.idPointsMarker.visible = false // pb is here
}
}
MapItemView {
model: searchModel
delegate: Marker{
coordinate: place.location.coordinate
}
}
}
}
I wish to toggle the visibility to false on doubleclick. I am not able to access the property anyhow the way i write it. What is the correct syntax?
Sorry for a so simple question. Thanks for help.
You do not have to set the property in main.qml, you must do it in Marker.qml, since the elements of Marker.qml can access all the elements of main.qml. One solution is to establish a property of type bool that manages the visibility and that changes in the double click:
main.qml
Map {
[...]
property bool isVisibleItems: true
MouseArea {
id : mouseMap
anchors.fill: parent
onDoubleClicked: map.isVisibleItems = !map.isVisibleItems
}
[...]
Marker.qml
import QtQuick 2.0
import QtLocation 5.6
MapQuickItem {
id: idPointsMarker
sourceItem: Loader{sourceComponent: idRect}
visible: map.isVisibleItems
Component{
id: idRect
Rectangle{
width: 20
height: 20
color: "blue"
}
}
}
In the following link there is an example

Interaction between two QML files

I want to use some qml file(main.qml) but before that I need to get some authentication info from user(login, pass). So I want to do this in the second window(login.qml). I saw Qt.createComponent for opening second qml file, but I can't get any information from this type of window.
So how can I use some information from the second window in the first window?
Or how can I dynamically load these items(main.qml, login.qml) in the parent qml file?
So how can I use some information from the second window in the first
window?
This is just one way of doing it:
main.qml
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
ApplicationWindow {
width: 400
height: 400
visible: true
ColumnLayout {
id: logItems
height: 200
Button {
id: loginButton
onClicked: loginForm.visible = true
text: "Log in"
}
Login {
anchors.top: loginButton.bottom
id: loginForm
visible: false
onLoginInfo: {
logInfo.text = "User:" + user + " password: " + password
}
}
}
Text {
id: logInfo
anchors.top : logItems.bottom
}
}
Login.qml
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
Item {
signal loginInfo(string user, string password)
ColumnLayout {
RowLayout {
TextField {
id: user
}
TextField {
id: password
}
}
Button {
text: "Submit"
onClicked: loginInfo(user.text, password.text)
}
}
}
How can I dynamically load QML items from separate files/resources in
another QML file?
Qt.CreateComponent allows you to use JavaScript to dynamically create and use QML code from other files.

QML: move to next control in form

How can I move focus from one control to next one inside QML form?
By default it works with Tab button but I need to change it to Enter.
All the control are ordered with Gridlayout with 2 columns.
I've defined a new component, TextFieldMoveOnReturn.qml
import QtQuick 2.0
import QtQuick.Controls 1.1
TextField {
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
If you use this one instead of TextField, you get the required behaviour
edit a better solution: define a new component GridLayoutNextOnReturn.qml
import QtQuick 2.0
import QtQuick.Layouts 1.1
GridLayout {
Keys.onReturnPressed: {
for (var i = 0; i < children.length; ++i)
if (children[i].focus) {
children[i].nextItemInFocusChain().forceActiveFocus()
break
}
}
}
and use normal TextField inside - works like a charm
In order to make it more robust and flexible, you should make same behaviour
for Tab and Enter/Return keys.
Handle keyPressed event and use KeyNavigation.tab instead of nextItemInFocusChain to focus next element as follow:
import QtQuick 2.12
import QtQuick.Controls 1.12
Column {
TextField {
id: field1
KeyNavigation.tab: field2
activeFocusOnTab: true
Keys.onReturnPressed: KeyNavigation.tab.forceActiveFocus();
}
TextField {
id: field2
KeyNavigation.tab: field3
activeFocusOnTab: true
Keys.onReturnPressed: KeyNavigation.tab.forceActiveFocus();
}
TextField {
id: field3
KeyNavigation.tab: field1
activeFocusOnTab: true
Keys.onReturnPressed: KeyNavigation.tab.forceActiveFocus();
}
}
So you controlled order of focus and users can use both tab and return keys interchangeably which results better UX.
Whenever you want to change order, just change KeyNavigation.tab values :)
Note: I extremely suggest you to avoid using nextItemInFocusChain because of future changes and flexibility
You can use onEditingFinished:
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
Rectangle {
width: 400
height: 400
GridLayout {
anchors.fill: parent
columns: 2
Label {
text: "Name"
}
TextField {
onEditingFinished: addressEdit.focus = true
}
Label {
text: "Address"
}
TextField {
id: addressEdit
}
}
}
Use Keys.onReturnPressed and forceActiveFocus()
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
Rectangle {
width: 400
height: 400
GridLayout {
anchors.fill: parent
columns: 2
Label {
text: "Name"
}
TextField {
Keys.onReturnPressed: organizationEdit.forceActiveFocus()
}
Label {
text: "Organization"
}
TextField {
id: organizationEdit
Keys.onReturnPressed: addressEdit.forceActiveFocus()
}
Label {
text: "Address"
}
TextField {
id: addressEdit
}
}
}

Resources