qt-items-新しいフレームワーク、またはすべての理論を見つける試み

ご存じのように、物理学者は長い間、すべての理論を見つけようとしてきました。 一般化の傾向は、物理学者だけでなく、数学者やプログラマーにも固有のものです。 広範囲の現象を説明および予測するエンティティの数が少ないことは非常に貴重です。 プログラマーにとって、理論はさまざまなAPIとフレームワークです。 高度に専門化された問題を解決するものもあれば、普遍的な理論の役割を主張するものもあります。 後者の例は、主にGUIの開発を目的としたユニバーサルフレームワークであるQtです。



次に、Qtについて好きではないことと、仕事のためにQtをさらに普遍的で強力かつ便利にする方法を説明します。



デモビデオ(HDで見るのが良い):







Qtは、他の多くのGUIフレームワークと同様に、単純なものから複雑なものに進化しています。 最初に単純なウィジェットが作成され、次により複雑で複雑なウィジェットが作成されました。 モデル/ビューフレームワークは、テーブルまたはツリービューでデータを表示するために登場しました。 グラフィック要素のセットを表示するグラフィックアイテムフレームワークが登場しました。 これらのフレームワークにはすべて異なるAPIがあり、相互に互換性がありません。 実際、1つの大きな理論の枠組みの中で、3つの独立したほぼばらばらの理論があります。 新しい視覚要素を開発する必要がある場合、3つのフレームワークのどれを使用するかを選択し、適切なAPIを適用する必要があります。 したがって、個別のウィジェットとして使用でき、テーブルセルに埋め込まれ、グラフィックシーンのノードで使用できる要素を作成することはできません。



Qtはスローガンの下で開発されています-一度書いて、そこで実行します。 これは最終的なアプリケーションの作成には当てはまるかもしれませんが、ライブラリ自体の拡張とカスタマイズには当てはまりません。



Qtライブラリが真に統合され強力になるように、ウィジェットをどのように配置すべきかを考えてみましょう。



さまざまなウィジェット(チェックボックス、テーブル、ツリー、グラフィックシーン)を見て、それらの共通点を見つけてみましょう。 それらの情報は、セル(アイテム)にグループ化されます。 チェックボックスは1つのセルで構成され、テーブルはセルの行と列で構成され、シーンのセルはノードです。 したがって、すべてのウィジェットにはセルが表示され、スペースの数と位置のみが異なるタイプのウィジェットに固有であると言えます。 ウィジェットがセルのスペースSpace )を表示するとします。 単純なウィジェットの場合、セル空間はSpaceItemにとって重要であり、単一のセルで構成されます。 テーブルの場合、セルを行と列に編成する方法を記述するSpaceGridを考えることができます。 グラフィックシーンにはSpaceSceneがあり、セルを好きな場所に配置できます。



基本クラスに区別できるすべてのスペースの共通点は何ですか?

これまでのところ、2つのことを区別できます。

  1. スペースの合計サイズを返します(通常、これはすべてのセルの境界ボックスです)
  2. 座標ItemIDでセルの位置を返します




class Space { virtual QSize size() const = 0; virtual QRect itemRect(ItemID item) const = 0; };
      
      





セル自体を詳しく見てみましょう。 明確にするために、次の表を検討します。







セルにも構造があります。 たとえば、チェックボックスは、チェックマークとテキストが付いたボックスで構成されます。 テーブル内のセルは非常に複雑になる場合があります(ビデオの例のように、テキスト、写真、リンクを含む)。 テーブルの場合、原則として、同じ列のセルは同じ構造を持つことに注意してください。 したがって、すべてのセルではなく、セット全体を記述する方が簡単です。 セルのセット( Range )は異なる場合があります。たとえば、すべてのRangeAllセル、RangeColumn列のセル、RangeRow行のセル、RangeOddRow行のセルなどです。 基本クラスRangeにはどのインターフェイスを割り当てることができますか? インターフェイスはシンプルで簡潔です-質問に答えるために、 範囲内の任意のセルであるかどうか:



 class Range { virtual bool hasItem(ItemID item) const = 0; };
      
      





セルのサブセットを決定したら、これらのセルに表示する情報の種類を指定する必要があります。 Viewクラスは、最小で分割できない情報を表示する役割を果たします。 たとえば、 ViewCheckはチェックボックスアイコン、 ViewText-テキスト行などを表示できます。



これまでのところ、基本Viewクラスはセルに情報を描画することしかできません。



 class View { virtual void draw(QPainter* painter, ItemID item, QRect rect) const = 0; };
      
      





問題は、セルの左側にアイコンを描画する必要があることをViewCheckがどのように認識し、チェックボックスアイコンの後にテキストを描画する必要があることをViewTextが認識するかです。 これを行うために、別の「ドワーフ」クラスLayoutがあります。 このクラスは、セル内にビューを配置できます 。 たとえば、LayoutLeftはビューをセルの左端に配置し、LayoutRight-右側、およびLayoutClient-はセルのスペース全体を占有します。 基本的なインターフェイスは次のとおりです。



 class Layout { virtual void doLayout(ItemID item, View view, QRect& itemRect, QRect& viewRect) const = 0; };
      
      





doLayout関数は、itemRectおよびviewRectパラメーターを変更して、ビューが項目セル内に配置されるようにします。 たとえば、LayoutLeftは、セルに情報を表示するためにビューに必要なサイズを要求し、itemRectから必要なスペースを「食いつぶし」ます。 ご覧のとおり、 Viewインターフェースにはもう1つの機能が必要です-サイズ:



 class View { virtual void draw(QPainter* painter, ItemID item, QRect rect) const = 0; virtual QSize size(ItemID item) const = 0; };
      
      





結果として、特定のスペースのセルにどのように表示するを説明するには、トリプルのオブジェクトタプル<Range、View、Layout>をリストする必要があります。 このようなトリプルItemSchemaを呼び出しましたSpaceクラス全体は次のようになります。



 class Space { virtual QSize size() const = 0; virtual QRect itemRect(ItemID item) const = 0; QVector<ItemSchema> schemas; };
      
      





ここに良い例があります(署名は少し時代遅れですが、主なアイデアは理解できると思います):







RangeView、およびLayoutクラスの異なる子孫を作成し、それらをさまざまな方法で結合することにより、任意のセルスペース、したがって任意のウィジェットをカスタマイズするための豊富な可能性があります。 たとえば、星の形で評価を表示するViewRatingクラスを作成することで、別のウィジェットとして、テーブルセル、およびグラフィックシーンの要素で使用できます。



このアーキテクチャは、プログラマの協力に役立ちます。 誰かが独自の種類のセル空間を記述できます。これにより、特別な方法でセルがスタックされます。 誰かが特定のデータを表示するビューを作成します。 そして、これらのプログラマーはお互いの仕事を活用できます。 これは、Viewクラスの実装の完全なリストではなく、作成と使用が簡単です(実装はほんの数行のコードです)。

  1. ViewButton-ボタンを描画します。
  2. ViewCheck-チェックボックスアイコンを描画します。
  3. ViewColor-特定の色で領域を塗りつぶします。
  4. ViewEnumText-限られたリストからテキストを描画します。
  5. ViewImageViewPixmapViewStyleStandardPixmap-画像を描画します。
  6. ViewLink-テキストリンクを描画します。
  7. ViewAlternateBackground-スルーストリップを描画します。
  8. ViewProgressLabelViewProgressBox-進行状況バーまたはパーセントを描画します
  9. ViewRadio-ラジオボタンアイコンを描画します。
  10. ViewRating-評価アイコンを描画します。
  11. ViewSelection-選択したセルを描画します。
  12. ViewText-テキストを描画します。
  13. ViewTextFont-後続のテキストのフォントを変更します。
  14. ViewVisible-別のビューを表示または非表示にします。




続けましょう。 原則として、ウィジェットはセルスペース全体を表示するのではなく、表示部分のみを表示します。 Spaceクラスは、セルスペースを記述するのに便利ですが、限られた可視領域のセルをレンダリングするには適していません。 CacheSpaceのサブエリアを表示する特別なクラスを定義しましょう:



 class CacheSpace { // reference to items space Space space; // visible area QRect window; // draw cached items void draw(QPainter* painter) const; // visit all cached items virtual void visit(Visitor visitor) = 0; };
      
      







CacheSpaceの特定の後続( CacheGridCacheSceneなど)は、キャッシュされたCacheItemセルのセットをさまざまな方法で格納します(ただし、このタイプのスペースに最適です)。 したがって、キャッシュされたすべてのセルを訪問する基本クラスの訪問関数を強調表示します。 これを使用すると、draw関数を簡単に実装できます。キャッシュされたすべてのセルにアクセスし、それらのセルでdraw関数を呼び出すだけです。



名前が示すように、 CacheItemは特定のセルを表示するために必要なすべての情報を保存します。



 class CacheItem { ItemID item; QRect itemRect; QVector<CacheView> views; void draw(QPainter* painter) const; };
      
      





ここで、draw関数も非常に単純です。ループ内で、 CacheViewクラスでdrawを呼び出します。これにより、セル内の最小で分割できない情報がレンダリングされます。



 class CacheView { View view; QRect viewRect; void draw(QPainter* painter, ItemID item) const; };
      
      







したがって、ウィジェットにはCacheSpaceが必要であり、それを使用してセル空間のコンテンツを描画する必要があります。



 class Widget { // space of items Space space; // cache of visible area of space CacheSpace cacheSpace; void paintEvent(QPaintEvent *event) override; void resizeEvent(QResizeEvent *event) override; };
      
      





resizeEventハンドラーでは、cacheSpace.windowオブジェクトの表示領域を変更し、paintEventハンドラーでは、そのコンテンツcacheSpace.draw()を描画します。



ご覧のとおり、オブジェクトの階層構造CacheSpace-> CacheItem-> CacheViewを使用すると、ウィジェットの視覚的構造全体を詳細に「見る」ことができます。 CacheSpaceレベルから別のCacheItemセルのレベルまで下がって、さらにセル内の個々のCacheViewsを並べ替えることができます。



ウィジェットを階層として表示するこの機能CacheSpace-> CacheItem-> CacheViewは、ウィジェットを管理および内省するための素晴らしい機会を提供します。



たとえば、自動テストシステムから任意のウィジェットにアクセスするための単一のインターフェイスを実装できます。 GUI自動テストシステムは通常、ウィジェット内の必要な領域を要求し、マウスでこの領域に作用して、ユーザーアクションをシミュレートします。 そのようなシステムに、影響を受ける可能性のある領域の最も詳細な「マップ」を提供できます。



別の例は、ビデオの例で示されているアニメーションです。 ウィジェットの構成を見るだけでなく、そのコンポーネントに作用することもできます。 たとえば、階層内のオブジェクト(CacheSpace-> CacheItem-> CacheView)の場所を時間的に変更したり、半透明で描画したりできます。 したがって、すべてのウィジェットおよびセル空間に適用できるアニメーションのライブラリ全体を収集できます。



その結果、このライブラリをカスタマイズできる方向をもう一度リストします。

  1. スペース -独自のタイプのセルスペースを作成できます
  2. CacheSpace-新しいタイプの表示スペースを作成できます。たとえば、CacheSpaceCouruselを実装します-カルーセルの形式でセルのリストを表示します
  3. ビュー -セルの新しい種類の視覚化を作成します
  4. アニメーション -新しいアニメーションを作成する




このメモは、前の2つ、 ここここの続きですqt-itemsプロジェクトは、これらのメモからのアイデアの実装です。



さらなる開発のためのアイデアやタスクがまだたくさんありますので、連絡を取り合いましょう。



All Articles