5

QtQuick 2 では、QtQuick コントロールを使用して複雑なデスクトップ アプリを作成できます。ただし、アプリの開始時にUI全体を宣言して一度に作成する必要があるようです。まだ使用したくない部分 (たとえば、[ファイル] -> [開く] ダイアログ) は作成する必要がありますが、次のように非表示になっています。

ApplicationWindow {

  FileDialog {
    id: fileOpenDialog
    visible: false
    // ...
  }
  FileDialog {
    id: fileSaveDialog
    visible: false
    // ...
  }
  // And so on for every window in your app and every piece of UI.

さて、これは単純なアプリでは問題ないかもしれませんが、複雑なアプリや多くのダイアログを持つアプリでは、これは確かにクレイジーなことですか? 従来の QtWidgets モデルでは、必要に応じて動的にダイアログを作成していました。

これにはいくつかの回避策があることを知っています。たとえばLoader、JavaScript で直接 QML オブジェクトを使用したり、動的に作成したりすることもできますが、それらは非常に醜く、優れた QML 構文の利点をすべて失います。また、コンポーネントを実際に「アンロード」することはできません。できるとよくLoader言っていますが、試してみたらアプリがクラッシュしました。

この問題に対するエレガントな解決策はありますか? それとも、単に弾丸をかじって、アプリのすべての潜在的な UI を一度に作成してから、そのほとんどを非表示にする必要がありますか?

注:このページには、これを回避するための s の使用に関する情報がありますが、ご覧のとおり、これLoaderはあまり良い解決策ではありません。

編集 1 - Loader が最適ではないのはなぜですか?

わかりました、なぜLoaderそれほど楽しくないのかを示すために、複雑なタスクを開始して結果を待つこの例を考えてみてください。人々が通常与える些細な例とは異なり、タスクには多くの入力といくつかの出力があるとします。

これがLoader解決策です:

Window {
    Loader {
        id: task
        source: "ComplexTask.qml"
        active: false
    }
    TextField {
        id: input1
    }
    TextField {
        id: output1
    }
    Button {
        text: "Begin complex task"
        onClicked: {
                // Show the task.
                if (task.active === false)
                {
                    task.active = true;
                    // Connect completed signal if it hasn't been already.
                    task.item.taskCompleted.connect(onTaskCompleted)
                }

                view.item.input1 = input1.text;
                // And several more lines of that...
            }
        }
    }

    function onTaskCompleted()
    {
        output1.text = view.item.output1
        // And several more lines...

        // This actually causes a crash in my code:
//      view.active = false;
    }
}

なしでそれを行っていた場合Loader、次のようなものになる可能性があります。

Window {
    ComplexTask {
        id: task
        taskInput1: input1.text
        componentLoaded: false
        onCompleted: componentLoaded = false
    }

    TextField {
        id: input1
    }
    TextField {
        id: output1
        text: task.taskOutput1
    }

    Button {
        text: "Begin complex task"
        onClicked: task.componentLoaded = true
    }
}

それは明らかにずっと簡単です。私が明確に望んでいるのは、が true に設定されているComplexTaskときに をロードして宣言的な関係をすべてアクティブにし、が false に設定されてcomponentLoadedいるときに関係を切断してコンポーネントをアンロードするcomponentLoaded方法です。現在、Qt でこのようなものを作成する方法はないと確信しています。

4

3 に答える 3

-2

すべてのユーザーが 2GB 以上の RAM を持っているため、要素のロードとアンロードはもはや現実的ではないと思います。

また、アプリが 512 MB 以上の RAM を使用できると思いますか? 疑わしい。

qml 要素をロードし、アンロードしないでください。クラッシュは発生しません。すべてのポインターを保存し、qml フレームを操作するだけです。

すべての QML 要素を RAM に保持し、その状態を保存すると、動作が速くなり、見栄えが良くなります。

例は、そのように開発された私のプロジェクトです: https://youtube.com/watch?v=UTMOd2s9Vkk

すべてのウィンドウに継承されるベース フレームを作成しました。このフレームには、メソッド hide/show および resetState があります。ベース ウィンドウにはすべての子フレームが含まれているため、シグナル/スロットを介して、他のフレームが次に必要なフレームを表示/非表示にします。

于 2014-11-06T13:14:48.240 に答える