0

In my Qt Quick(Qt v5.4 and QtQuick 2.4) project I have these five .qml files:

  1. MainForm.ui.qml - Which contains the main window of the application
  2. main.qml - Contains all the functionality implementations of objects of mainForm.ui.qml, such as onClicked events, calling c++ functions getting value from textInputs etc.

Q: Is my current setup for implementing functionality correct? Or should I implement all these things in the same file??

  1. dialog1.qml - Contains some text inputs for some settings etc.
  2. dialog2.qml - For some lists and tables in my application.
  3. dialog3.qml - Also contains some objects for an c++ function.

All these qml files are created and destroyed at different times, on different button clicks. I'm using this method to open a dialog

`addMenuArea.onClicked: {
Qt.createComponent("addMenuAppDialog.qml").createObject(rootWindow, {});
}`

and for destroying the dialog:

MouseArea{
    anchors.fill: parent
    onClicked: {
        dialogComponent.destroy()
    }
}

Now currently these dialogs doesn't have any functionality, like the main window, I want to do implement it all in one file(main.qml) without any javascript if possible. I have no Idea on how to link all the dialogs and main.qml so I can add the functions in main.qml. Any help will be great!

Amol Borkar
  • 2,321
  • 7
  • 32
  • 63
  • Which qt and which qt-quick? Version info missing. – user1095108 Jan 09 '15 at 15:36
  • @user1095108 Edited the question, take a look! – Amol Borkar Jan 09 '15 at 15:45
  • This is one possible way. Another way would be to use `Loader` and change out the source file name. This would handle the creation/destruction of the objects. The third way would be to instantiate all the dialog and hide all of them except for the one that should be visible, but this uses more memory than needed. – saiarcot895 Jan 09 '15 at 17:12
  • @saiarcot895 I'm searching the docs for this. Is there some method or function in `Loader` which will link the dialogs and main.qml?? – Amol Borkar Jan 09 '15 at 17:18
  • @EdwardMckinzie: `Loader.item` contains a reference to the top-level object that gets loaded. You can use that in conjunction with `Loader.source`. – saiarcot895 Jan 09 '15 at 17:21
  • @saiarcot895 Ok, I tried that in my project, the dialogs are loading fine. But the properties such as `onClicked` or `textEdit.text()`, still seem inaccessible from `main.qml`. Any idea on how should I proceed? – Amol Borkar Jan 09 '15 at 17:51
  • Signals such as `onClicked` from loaded component can be connected using [Connections](http://doc.qt.io/qt-5/qml-qtquick-loader.html#receiving-signals-from-loaded-objects). And use [Loader.item](http://doc.qt.io/qt-5/qml-qtquick-loader.html#item-prop) to access functions. – mcchu Jan 10 '15 at 07:26
  • @mcchu Thanks for the reply! Can you please elaborate on exactly how to do that, where the code for loader and connections goes? Perhaps some example code? – Amol Borkar Jan 10 '15 at 08:11

2 Answers2

1

Assume that you have a SimpleDialog.qml file:

Window { //or Item, Rectangle, ... whatever
    signal userPressedSomething()
    property string userNameString
    function textEditText(){ /*return textEdit.text()*/ }
    //...
}

And assume that your main.qml has the following functions which try to handle the necessary program logic:

  1. openSimpleDialog() to load the SimpleDialog
  2. closeSimpleDialog() to close the SimpleDialog
  3. userPressedSomethingInSimpleDialog()
  4. getSimpleDialogInfo()

You can use Loader to load, unload, obtain data from the dialog, and use Connections to catch signals. Here is a simple example in main.qml:

Loader { id: simpleDialogLoader }

function openSimpleDialog() { simpleDialogLoader.source = "SimpleDialog.qml"; }

function closeSimpleDialog() { simpleDialogLoader.source = ""; }

function getSimpleDialogInfo() {
    if (simpleDialogLoader.source !== "SimpleDialog.qml") { return; }
    console.log(simpleDialogLoader.item.userNameString); //property
    console.log(simpleDialogLoader.item.textEditText()); //function
}

Connections {
    target: simpleDialogLoader //to Loader
    onUserPressedSomething: { userPressedSomethingInSimpleDialog(); }
}

Let's explain the detail:

  • Use Loader.source property to dynamically load/unload SimpleDialog in the openSimpleDialog and closeSimpleDialog functions.
  • Loader.item holds the object created by the loader, and this is all the getSimpleDialogInfo needs.
  • Signals from SimpleDialog can be caught by set the Connections.target to Loader.item.
mcchu
  • 3,309
  • 1
  • 20
  • 19
  • Thanks! If I want to implement a function that changes some text or some color when a button in simpleDialog.qml, as I said I want to implement in main.qml? Also I wanted to know how to add do I get the values of sliders or `textEdit` when a button in simpleDialog.qml is pressed? I want to use these values as parameters in a C++ function? – Amol Borkar Jan 10 '15 at 13:23
  • If you want to change some text in SimpleDialog.qml when user press something in main.qml, try the `getSimpleDialogInfo` method. On the other hand, if you want to change some text in main.qml when user press something in SimpleDialog.qml, try the `Connections` method (SimpleDialog should emit signal explicitly). C++ is not required in both scenarios. – mcchu Jan 10 '15 at 15:34
1

Though you can define all the dialogs and main window in main.qml file, I strongly discourage this approach. As your dialogs and your main window grow in complexity (they definitely will become more complex), your QML code will become harder and harder to understand.

Doing

Qt.createComponent("addMenuAppDialog.qml").createObject(rootWindow, {})

involves loading QML file from HDD so I don't recommend calling it on every mouse click. I suggest 2 alternatives to that approach.

Alternative 1

Create a component for each dialog inside your main window:

Component {
    id: dialog1Component
    Dialog1 {}
}

Then you'll be able to create it by calling dialog1Component.createObject(rootWindow, {}), and you'll still need to destroy it manually when it closes.

Alternative 2

This is approach that is used in my app to present dialogs.

Create dialog declaratively (place it inside your main window):

MainWindow {
    Dialog1 {
        id: dialog1
    }
}

Then you'll be able to show it by calling dialog1.open() and to hide it by calling dialog1.close().

tonytony
  • 1,994
  • 3
  • 20
  • 27
  • Thanks! In alternative 2 is it possible to add custom QML components, like `ListView` or TextInputs, with their own custom styles or use another qml files as componets?? – Amol Borkar Jan 10 '15 at 11:25
  • @EdwardMckinzie Yes, you definitely can do something like `MainWindow { Dialog1 { TextInput { /* blah blah blah */ } } – tonytony Jan 10 '15 at 15:22