2016-08-31 7 views
7

タイルで満たされた巨大な長方形のグリッドを想像してください。個々のタイルはあまり複雑ではなく、少量の形状を含むSVG画像です。QMLで巨大なタイルを扱う方法は?

非常に大きくないタイルの種類の数は、私は低いと推定します。しかし、グリッドは非常に大きくなる可能性があるため、タイルの総数は膨大です(少なくとも数万、おそらくそれ以上)。

グリッドを水平方向と垂直方向にスムーズにスクロールできるだけでなく、スムーズにズームイン/ズームアウトできるようにする必要があります。私はまた、特定の位置にジャンプすることができなければなりません。

私は非同期的に、最初に実際に表示されている要素、残りの要素を取り込めるといいですね。つまり、最初にループ内に行と列を追加する必要があるテーブル処理クラスは、開始位置が必ずしも左上隅ではないため、最適な解決策ではありません。

ズームは、スケーリング係数の倍数として指定されたタイル内の項目のすべてのプロパティを持つことによって簡単に達成されます。 svgは、異なるイメージの数が多くないため問題にはなりません。キャッシュできる必要があります。万一、svgがボトルネックになった場合、異なる解像度の異なるpngのセットを使用できます。

Iは、以下のアプローチを試みた(または考え):動的(Component.createObject)をQMLオブジェクトを作成、SameGame exampleの方法を用いて

  1. を。これは、オブジェクトの数が少ないが、多数のオブジェクトで非常に遅い場合に機能します。オブジェクトが完全に空であっても、このメソッドはvery long timeになります。

  2. Flickableの中にRepeaterを使用する。 FlickableにはGridが含まれ、Repaterが入力されています。もちろん、Gridは莫大です。 このメソッドは、オブジェクトを動的に作成するよりも高速ですが、タイルの数が増えるにつれて効率的ではありません。 QMLエンジンは、表示されていないアイテムも含め、すべてのアイテムを追跡します。すべてのアイテムのプロパティが目に見えるものだけでなく再計算されるので、ズームも非常に遅いです。

  3. GridViewを使用する。一見したところ完璧なソリューションのようです。 GridViewFlickableを継承し、ビューの範囲内にあるコンテンツのみを表示するようにも注意します。何百万ものsvgイメージを持つテストケースでさえ、合理的に高速で実行され、スムーズにスクロールしてサイズを変更します。問題は1つだけです:GridViewは、水平または垂直のいずれかでフリッキングできますが、両方ではありません。 2012年以来これについてfeature requestがありましたが、まだ無視されているようです。

  4. QGraphicsViewを直接使用する。必要な量の要素を表示、スクロール、ズームすることはis capableですが、QMLベースではありません。私の残りのGUIはQMLであり、QMLQGraphicsViewを組み合わせるという恐怖の話しか読まなかった。私はそれの合理的な例を見たことがない。

その他の解決策はありますか?Flickableの中を移動している間に、単純なGridLayoutの行と列を追加したり削除したりするためにJavascriptを使用するという恐ろしいハック(いくつかの行と列は可視領域よりも大きい)または、OpenGLウィンドウを埋め込み、すべてを手動で描画するだけですか?

私はこれが不可能な仕事ではないことを願っています。 20年以上前にDOSやWindows 95用に書かれた戦略ゲームで、この量のタイルを扱うことができました。テクスチャとアニメーションが追加されました。

+1

DOSとWindows 95との比較は、基礎となる技術とアプローチが大きく異なるため、意味をなさない。必要なものを実行するカスタムのQtQuick要素を使用しないのはなぜですか? – peppe

+0

@peppe:私の論点はシステム自体ではありませんでしたが、200倍少ない計算能力でそれを行うことができました。そして「カスタムQtQuick要素」によって、自分の2Dグラフィックスエンジンを最初から実装する必要があることを意味しますか?はい、可能ですが、そのアプローチはOpenGL描画ソリューションに似ています。 'GridView'はいつ、何をロードしてアンロードするのかを知る利点がありました。すべてをゼロから行うことで、私は自分のメモリ管理、可視性の計算などを実装する必要があります。私が最初からすべてを実装しなければならないのなら、なぜQtを使うのですか? – vsz

+1

あなたは今日でも完全に可能ですが、10000要素のリピーターは間違ったアプローチです。このような組み込みのものがQMLに欠けているということは、実現不可能というわけではありません。 – peppe

答えて

1

Qtは、非常に有用であり、重要であると考えられ、zip supportのように、一番上に投票されたとしても、何年もコミュニティーの提案を無視することができます。

私は個人的には「固定」GridViewを気にしませんが、C++では自分の特定の要件に合わせてゼロから何かを実装しているので、高速かつ効率的です。あなたのタイルが均一な四角形であれば、それは非常に簡単です、そして、たとえ内部の実際のイメージが正方形でなくても、それを取り除くことができるように聞こえます。これにより、プログラム上の位置を決定するのが非常に簡単になります。また、左上隅のタイル、1行あたりのタイル数、後続の線の幅も決定できます。次に、可視領域の矩形が移動すると、コンテナと信号を繰り返して、可視性を入力する要素のQML要素を作成します。簡単なピーシー。

あなたは何も気にせずに、QObjectを継承し、そのタイプをQMLに登録して、内部の「モデル」に移入して入力します。あなたは間違いなく、シーングラフがそれらをレンダリングしないほどスマートであっても、それらを処理しているにもかかわらず、メモリ内のすべてのオブジェクトを持っていないと思う、私はあなたのFPSの低下がGPUの製品ではなくCPUのボトルネック。

実際のグリッドオブジェクトは、データQ_SIGNAL void create(x, y, imgPath);を使用して作成および破棄信号を出力することができるため、「デリゲート」オブジェクトを簡単に指定するなど、柔軟性と使いやすさを提供するカスタムハンドラをQML側にバインドします。 C++で実際の作成/破壊を行うよりもエレガントになります。あなたがすべての「生きている」オブジェクトを追跡する必要がないので、複雑さを最小限に抑えるために、自己破棄するために画面外に出たときに追跡できるように見える少数のアイテムに対しては、QML側でバインディングを使用できます。

Component { 
    id: objComponent 
    Image { 
     property bool isVisible: { is in grid.visibleRect ??? } 
     onIsVisibleChanged: if (!isVisible) destroy() 
    } 
} 

MyGrid { 
    id: grid 
    contentX: flickable.contentX 
    contentY: flickable.contentY 

    onCreate: objComponent.createObject(flickable.contentItem, {"x" : x, "y" : y, "source" : imgPath}) 
} 

Flickable { 
    id: flickable 
    contentWidth: grid.contentWidth 
    contentHeight: grid.contentHeight 
} 

ユーザーは、私が働いてコードを生成したいの恩恵を提供するのに十分な重要な問題を、持っているが、残念ながら私は現在、あまりにも忙しく、通常、。このコンセプトはかなり単純ですが、実装するのにもあまり問題にならないはずです。

+2

GridView *はC++で実装されています。 –

+0

@ DavidK.Hess - また、それは主張していない? – dtech

関連する問題