I am developing an application with Qt and qml and I am building it for OSX, iOS and Android. The application contains a StackView which has only three pages. In the second page I have a five MenuItems and five Dialogs.
While this very simple application has an excellent performance when runs on OSX and Android, it delays up to 3-4 seconds to show the second page on iOS.
I have already tried "Qml Profiler" and I have found out that the delay happens during the creation of the qml file that describes the second page.
I have also tried "Qt Quick Compiler" (Commercial Qt) with no significant difference.
main.qml
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
ApplicationWindow {
id: app
title: "MyApp"
width: 1024
height: 768
visible: true
StackView {
id: stackView
anchors.fill: parent
initialItem: firstPage
}
Component {
id:firstPage
FirstPage {
}
}
}
firstPage.qml
import QtQuick 2.3
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
Item {
id:firstPage
signal collectionClicked(string name)
focus: true
objectName: "firstPage"
Rectangle {
anchors.fill: parent
color: "blue"
}
MouseArea {
anchors.fill: parent
onClicked: {
stackView.push(Qt.resolvedUrl("SecondPage.qml"))
}
}
}
SecondPage.qml
import QtQuick 2.3
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
Item {
id: itemsPage
signal itemClicked()
Rectangle {
id: myRectangle
anchors.fill: parent
color: "red"
Dialog {
id: dialog1
height: 200
width: 300
//onAccepted: ;
}
Dialog {
id: dialog2
height: 200
width: 300
//onAccepted: ;
}
Dialog {
id: dialog3
height: 200
width: 300
//onAccepted: ;
}
Dialog {
id: dialog4
height: 200
width: 300
//onAccepted: ;
}
Dialog {
id: dialog5
height: 200
width: 300
//onAccepted: ;
}
Menu {
id: myMenu
title: "Menu"
MenuItem {
text: "Test"
//onTriggered: ;
}
MenuItem {
text: "Test"
//onTriggered: ;
}
MenuItem {
text: "Test"
//onTriggered: ;
}
MenuItem {
text: "Test"
//onTriggered: ;
}
MenuItem {
text: "Test"
//onTriggered: ;
}
}
}
MouseArea {
anchors.fill: parent
onClicked: stackView.push(Qt.resolvedUrl("ThirdPage.qml"));
}
}
ThirdPage.qml
import QtQuick 2.0
Item {
Rectangle {
anchors.fill: parent
color: "green"
Text {
text: "third page"
}
}
}
I have tried for such a long to find a solution. And I think that it is impossible that there is nobody that has ever tried to make a simple qml application for iOS and faced what I have faced.
Thank you,
Michael
Related
I'm trying to find a means of creating dynamic chartviews using QML. The general idea is for a user to click an element on a ComboBox and click a button to either add a chartview to the screen or remove it.
Currently I'm able to display my charts statically in a RowLayout like so:
import QtQuick 2.15
import QtCharts 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.12
Item{ property int firstModel : 1
property int secondModel : 2
property int maxVal : 8
property int minVal: -8
RowLayout {
anchors.fill: parent
spacing: 10
ChartView{
id: firstModelChartView
animationOptions: ChartView.NoAnimation
theme: ChartView.ChartThemeLight
antialiasing: true
Layout.fillHeight: true
Layout.fillWidth: true
DateTimeAxis{
id:axisXValues
min:new Date(SensorManager.audioStream[firstModel].xMin)
max:new Date(SensorManager.audioStream[firstModel].xMax)
format: "hh:mm:ss:zzz"
}
ValueAxis {
id: axisYValues
min: gLinkMin
max: gLinkMax
}
LineSeries {
id: innerChamberLineSeries
useOpenGL: true
name: "Inner Chamber"
axisX: axisXValues
axisY: axisYValues
}
VXYModelMapper {
id: innerChamberLineSeriesModelMapper
model: SensorManager.audioStream[firstModel]
series: innerChamberLineSeries
firstRow: 1
xColumn: 0
yColumn: 1
}
}
/// SEcond Model ...... Etc You get the gist
}
}
The model is a QAbstractModel Type from C++ and I'm able to display this in realtime. My problem is I've got 20 of these data streams and I don't want to show them all at once. so I want to give the user the ability to be able to add or remove multiple of these chartviews from the screen.
I'm trying to use a GridView and basically adapt this snippet from this post but I'm not really getting far with it.
My Idea is to initially create a chartview and then attach a lineseries to that chartview, here's what I've got so far but I'm stumped on how to attach a specific lineseries model to a chartview and how you remove a specific chartview from the Gridview.
import QtQuick 2.15
import QtCharts 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.12
Item{ property int firstModel : 1
property int secondModel : 2
property int maxVal : 8
property int minVal: -8
ListModel{
id: chartsModel
Component.onCompleted: {
chartsModel.append({"name": qsTr("Inner Vinration Chamber"), value: firstModel })
chartsModel.append({"name": qsTr("Extruder Vibration Y"), value: secondModel })
///////
}
}
ListModel{
id:chartViewModel
}
Row {
id: chartControlsRow
anchors.fill: parent
anchors{
leftMargin: 10
topMargin: 10
}
spacing:0
CustomComboBox {
id: chartSelector
model: chartsModel
textRole: "name"
onCurrentIndexChanged: {
var model = SensorManager.audioStream[chartsModel.get(currentIndex).value]
}
}
CustomButton
{
id: addChartButton
text: "Add Chart"
onClicked: {
modelId.append({'mColor': 'blue'})
var chartViewModel = Qt.createQmlObject('import QtQuick 2.14; ListModel { }',
Qt.application, 'dynamicChartViewModel');
}
}
CustomButton
{
id:removeChartButton
text: "Remove Chart"
onClicked: {
console.log(chartSelector.currentIndex)
chartViewModel.remove(chartSelector.currentIndex);
}
}
}
Rectangle{
anchors.fill: parent
anchors.topMargin: 55
color: "black"
GridView {
id: mGridViewId
anchors.fill: parent
cellWidth: 400; cellHeight: 400
model: chartViewModel
delegate: Rectangle {
width: mGridViewId.cellWidth;
height: mGridViewId.cellHeight
color: mColor
ChartView {
id: mChartView
width: parent.width;
height: parent.height
DateTimeAxis{
id:axisXValues
format: "hh:mm:ss:zzz"
}
ValuesAxis{
id:axisYValues
min:gLinkMin
max:gLinkMax
}
LineSeries {
name: "Lineseries"
id: mLineSeries
useOpenGL: true
axisX: axisXValues
axisY: axisYValues
}
VXYModelMapper{
id: modelMapper
series: mLineSeries
firstRow: 1
xColumn: 0
yColumn: 1
}
}
}
function getDelegateInstanceAt(index) {
return contentItem.children[index];
}
}
}
}
How do I Achieve this? Any tips or pointers would be helpful
I'm developping an app using QT 5.15 LTS (5.15.2). I have the following QML item that I use to handle virtual keyboard interactions :
//InputScreen.qml
import QtQuick 2.3
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.2
import QtQuick.VirtualKeyboard 2.3
Rectangle
{
id: inputScreen
property var target: undefined
width: app.width
height: app.height
color: "#44000000"
z: 200
onVisibleChanged:
{
if (inputScreen.visible == true)
{
fld.text = target.text;
inputPanel.forceActiveFocus();
fld.forceActiveFocus();
fld.clicked(); //Tried to force a click here. Explanation below
}
}
Rectangle
{
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
height: 40
width: 600
z: 201
TextField
{
id: fld
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: 400
height: 40
font.pixelSize: 24
focus: true
}
Button
{
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width: 200
height: 40
font.pixelSize: 24
text: "Valider"
onClicked:
{
if (target != undefined)
{
target.text = fld.text;
inputScreen.visible = false;
}
}
}
}
InputPanel
{
id: inputPanel
height: 400
width: app.width - 40
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
focus: true
z: 201
}
MouseArea
{
anchors.fill: parent
onClicked:
{
target.text = fld.text;
inputScreen.visible = false;
}
}
}
When my item becomes visible, the textField gets the focus correctly and I can start typing through the InputPanel virtual keyboard. There's however one single problem : the shift key does not work !
In order to make that shift key enable itself, I need to click on the TextField, which beats the purpose of forcing the active focus on it to begin with.
Is there any way to fix that problem ? Or at the very least, is there any kind of workaround I can use to enable that shift key ?
I have already tried to force a click inside my TextField (as seen in the code above), but it didn't work.
For context : here's the content of main.qml as well, in order to give out a working example :
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 1.4
import QtQuick.VirtualKeyboard 2.3
Window
{
id: app
visible: true
width: 640
height: 480
title: qsTr("Example")
InputScreen
{
id: inputScreen
visible: false
}
Rectangle
{
id: rect
height: parent.height * 0.8
width: parent.width * 0.8
anchors.centerIn: parent
border.color: "#FF0000"
z: 1
TextField
{
id: myField
anchors.centerIn: parent
width: 200
height: 24
MouseArea
{
anchors.fill: parent
onClicked:
{
inputScreen.target = myField;
inputScreen.visible = true;
}
}
}
}
}
I finally managed to find a trick that enabled that shift key without requiring to click on my already focused TextField, and it's actually very simple.
I simply added the following line in the onClicked event of the MouseArea inside the "myField" TextField :
MouseArea
{
anchors.fill: parent
onClicked:
{
parent.focus = true; //This line solved the issue !
//...
}
}
I have no idea why, but somehow this was enough to actually unlock the shift key from my InputPanel virtual keyboard without requiring me to click a second time on the TextField from my InputScreen item. I suppose it has probably something to do with the fact that my MouseArea is hijacking the focus of the "myField" TextField, which triggers some sort of odd behaviour on the InputPanel item despite having another TextField item focused.
In any case, I hope this will help someone.
I need to have a Popup that stays visible outside the bounds of the main window.
I couldn't find anything in the Qt documentation.
This is the code:
import QtQuick 2.15
import QtQuick.Window 2.2
import QtQuick.Controls 2.12
ApplicationWindow {
id: window
width: 400
height: 400
visible: true
Button {
text: "Open"
onClicked: popup.open()
}
Popup {
id: popup
x: 100
y: 100
width: 300
height: 400
modal: true
focus: true
dim: false
contentItem: Rectangle
{
anchors.fill: parent
color: "red"
}
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
}
}
This is the output of this:
I want the red to go beyond the window borders.
Something like this:
I'd appreciate the help!
Note: using a Dialog is no good for me.
Popups are not proper windows, so you'd need to create a new window like Michael mentioned:
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
id: mainWindow
width: 640
height: 480
visible: true
ApplicationWindow {
id: redWindow
x: mainWindow.x + mainWindow.width / 2
y: mainWindow.y + mainWindow.height / 2
width: 300
height: 400
flags: Qt.Popup | Qt.Dialog
visible: true
Rectangle {
color: "red"
anchors.fill: parent
}
}
}
There is a suggestion to make Popups proper windows here.
I am working on project with Qt Quick Control 2.
When I try to run my software in debug mode FileDialog.qml opens perfectly but when I deploy it as release mode it doesn't work.
Here is my code:
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls 1.3
import QtQuick.Dialogs 1.0
// File Dialog to browse
FileDialog {
id: openDialog
title: "Please Select An Image"
folder: shortcuts.pictures
nameFilters: ["Image files (*.BMP)"]
modality: Qt.NonModal
selectExisting: true
/*
* do my stuff
*/
}
Here it is my Js function that calls FileBrowse.qml (file in parameters).
I call this function in other view like this :
JsCommonCall.openFileDialog("frameFileBrowse.qml",2)
function openFileDialog(file,
parentCalled) {
_component = Qt.createComponent(file);
_popUp = _component.createObject(windowsMain, {"x": offsetPopUpCreate,
"y": offsetPopUpCreate,
"parentCall":parentCalled});
if(_popUp !== null)
_popUp.open()
}
here it is my FileBrowse
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Dialogs 1.0
// File Dialog to browse
FileDialog {
id: openDialog
title: "Please Select An Image"
folder: shortcuts.home
nameFilters: ["Image files (*.BMP)"]
selectFolder: true
// variables
property int parentCall;
onAccepted: {
imgCurrentCam1.source = openDialog.fileUrl;
openDialog.close()
}
onRejected: {
openDialog.close()
}
}
This is working for me
FileDialog {
id: fdExport
title: qsTr("File name")
folder: shortcuts.home
selectFolder: true
onAccepted: {
}
}
and to run
fdExport.open()
Please try to leave
modality: Qt.NonModal
from your code.
I don't know which is the problem but the code below is perfectly portable on Windows machines. Tested in Linux too.
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
FileDialog {
id: fdImport
title: qsTr("File name")
folder: shortcuts.home
onAccepted: {
textEdit.text= fdImport.fileUrls[0]
}
}
Rectangle {
id: rectangle
color: "#ffffff"
anchors.fill: parent
Rectangle {
id: rectangle1
color: "#ffffff"
anchors.right: parent.right
anchors.rightMargin: 8
anchors.left: parent.left
anchors.leftMargin: 8
anchors.bottom: rectangle2.top
anchors.bottomMargin: 6
anchors.top: parent.top
anchors.topMargin: 8
TextEdit {
id: textEdit
text: qsTr("Text Edit")
anchors.fill: parent
font.pixelSize: 12
}
}
Rectangle {
id: rectangle2
y: 441
width: 128
height: 32
color: "#ffffff"
anchors.left: parent.left
anchors.leftMargin: 8
anchors.bottom: parent.bottom
anchors.bottomMargin: 7
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: {
fdImport.open()
}
Text {
id: text1
text: qsTr("Click me!")
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors.fill: parent
font.pixelSize: 12
}
}
}
}
}
The qt.conf file
[Paths]
Plugins=plugins
Libraries=libs
Please remember to copy all the dll (release) in the executable folder, with the qml and plugins folders.
One strange but possible reason for it is anti-virus: my FileDialog isn't opening either, and the entire QML application is hanging, while the AV is active.
I need to call a C++ class method with parameters from UI after animation of SwipeView ends.
main.ui
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
SwipeView {
id: swipeView
anchors.fill: parent
Page1 {
id: page1
}
Page2{
id: page2
}
}
XOR {
id: xor
onXorEnded: {
//swipeView.setCurrentIndex(0)
}
onQChanged: {
page2.bar.value = xor.getq()
}
}
}
Page1Form.ui.qml
Page1Form {
kpButton.onClicked: {
kpDialog.visible = true
}
xorButton.onClicked: {
swipeView.setCurrentIndex(1)
xor.crypt(file_path.text, key_path.text, out_path.text)
}
fpButton.onClicked:{
fpDialog.visible = true
}
FileDialog {
id: fpDialog
onAccepted: {
file_path.text = fpDialog.fileUrl
}
}
FileDialog {
id: kpDialog
onAccepted: {
key_path.text = kpDialog.fileUrl
}
}
}
It seems like in xorButton.onClicked xoring starting before animation of swipe view ends. How it works now: Imgur
As a workaround you can bind your action to index changing:
xorButton.onClicked: {
swipeView.setCurrentIndex(1)
}
SwipeView {
id: swipeView
onCurrentItemChanged: {
if(currentIndex == 1)
xor.crypt(file_path.text, key_path.text, out_path.text)
}
}
But anyway, that fires not at end of animation.
As another workaround you can use StackView. It has more properties to control the animation. Another advantage of this control is that user cannot swipe it when you don't expect it. In your case an user just can swipe that. One more advantage is that page doesn't take memory when you don't need it.
import QtQuick 2.7
import QtQuick.Window 2.2
import QtQuick.Controls 2.0
Window {
visible: true
width: 800
height: 800
StackView {
id: view
anchors.fill: parent
initialItem: page1
onBusyChanged: {
if(!busy && currentItem.objectName == "page2")
currentItem.run();
}
}
Component {
id: page1
Rectangle {
color: "green"
objectName: "page1"
Button {
anchors.centerIn: parent
text: "swipe me"
onClicked:
view.push(page2)
}
}
}
Component {
id: page2
Rectangle {
color: "yellow"
objectName: "page2"
function run() { sign.visible = true; }
Rectangle {
id: sign
anchors.centerIn: parent
width: 100
height: 100
radius: 50
color: "red"
visible: false
}
}
}
}