1. グラフィックビューフレームワークの構造
上記の基本的な描画では、さまざまなグラフィックを自分で描画し、制御することができます。ただし、同じまたは異なるグラフィックを多数同時に描画する必要があり、それらの動きを制御したり、衝突や重ね合わせを検出したりする必要がある場合、または描画したグラフィックの位置をドラッグしたり、ズームしたり、回転したりできるようにしたい場合があります。従来の方法のままでは、これらの機能を実現することは非常に困難です。これらの問題を解決するには、Qt が提供するグラフィックス ビュー フレームワークを使用できます。
Graphics View フレームワークの主な機能は次のとおりです。
- グラフィックス ビュー (グラフィックス ビュー) は、カスタマイズされた多数の 2D グラフィックス アイテムを管理し、操作することができます。ビュー ウィジェットを使用すると、すべてのグラフィック アイテムを視覚化でき、ズームおよび回転機能も提供します。
- このフレームワークには、シーン内のグラフィック アイテムとの正確な倍精度対話を実行する機能を提供するイベント伝播フレームワークが含まれています。グラフィック アイテムは、キーボード イベント、マウス プレス、移動、リリース、およびダブルクリック イベントを処理でき、マウスの動きを追跡することもできます。
- グラフィックス ビュー フレームワークは、BSP (Binary Space Partitioning) ツリーを使用してグラフィックス アイテムを迅速に検出します。このため、数百万のグラフィックス アイテムを含む巨大なシーンをリアルタイムで表示できます。
- グラフィックス ビューのフレーム構造では、システムは Qt グラフィックス システムのアンチエイリアシング ツールと OpenGL ツールを使用して、グラフィックスのパフォーマンスを向上させることができます。
グラフ ビューの構造は主に 3 つの部分で構成されます。
- シーン (Scene): QGraphicsScene クラス
- ビュー (View): QGraphicsView クラス
- グラフィックアイテム (Item): QGraphicsItem クラス
この記事のメリット、Qt 開発学習教材パッケージの受け取り料金、技術ビデオ、コンテンツには (C++ 言語基礎、Qt プログラミング入門、QT シグナルとスロットのメカニズム、QT インターフェイス開発イメージ図、QT ネットワーク、QT データベース プログラミング、QT プロジェクト戦闘、QSS、OpenCV、Quick モジュール、インタビューの質問など) ↓↓↓↓↓↓ 下記を参照
1.1 シーン
シーンはグラフィック アイテムの QGraphicsItem オブジェクトのコンテナであり、その主なタスクには次のものが含まれます: |
以下は、QGraphicsScene の一般的に使用される関数の一部です。
- QGraphicsScene::addItem() 関数を呼び出してグラフィック アイテムをシーンに追加し、グラフィック アイテム検出関数のいずれかを呼び出して追加されたグラフィック アイテムを取得できます。
- QGraphicsScene::items() 関数と他のいくつかのオーバーロードされた関数は、基準を満たすすべてのグラフィックス項目を返します。これらのグラフィックス アイテムは、指定された点、四角形、多角形、またはベクトル パスと交差するか、その中に含まれます。
- QGraphicsScene::itemAt() 関数は、指定されたポイントの最上位のグラフィックス項目を返します。すべてのグラフィック アイテム検出関数は、グラフィック アイテムを降順で返します (たとえば、最初に返されたグラフィック アイテムが一番上にあり、最後に返されたグラフィック アイテムが一番下にあります)。
- シーンからグラフィック項目を削除したい場合は、QGraphicsScene::Removeltem() 関数を使用できます。
- シーン内の指定されたグラフィック項目は、任意の形状を QGraphicsScene::setSelectionArea() 関数に渡すことによって選択できます。
- 現在選択されているすべてのグラフィック項目のリストを取得したい場合は、QGraphicsScene::selectedltems() 関数を使用できます。
- さらに、 QGraphicsScene::setFocusItem() または QGraphicsScene::setFocus() 関数を呼び出してグラフィック項目のフォーカスを設定したり、 QGraphicsScene::focusItem() 関数を呼び出して現在フォーカスされているグラフィック項目を取得したりできます。
- QGraphicsScene::render() 関数は、シーンの一部をグラフィックス デバイスにレンダリングします。
まず最も単純な例を見てみましょう。新しい空の Qt プロジェクト (空の qmake プロジェクト) を作成します。プロジェクト名は myscene です。次に、main.cpp という名前の新しい C++ ソース ファイルをこのプロジェクトに追加します。追加が完了したら、まず myscene.pro ファイルにコード行を追加します。
QT += widgets
次に、main.cpp の内容を次のように変更します。
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QDebug>
int main(int argc,char* argv[ ])
{
QApplication app(argc,argv);
//新建场景
QGraphicsScene scene;
//创建矩形图形项
QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 100, 100);
//将图形项添加到场景中
scene.addItem(item);
//输出(50, 50)点处的图形项
qDebug() << scene.itemAt(50,50,QTransform());
return app.exec();
}
ここでは、最初にシーンが作成され、次に長方形のグラフィック アイテムが作成され、グラフィック アイテムがシーンに追加されます。次に、 itemAt() 関数を使用して、指定された座標にある最上位のグラフィック アイテムを返します。ここで返されるのは、追加されたばかりの長方形のグラフィック アイテムです。これでプログラムを実行できるようになりますが、ビューが設定されていないため、グラフィカル インターフェイスは表示されません。この時点では、次のようにアプリケーションの出力バーに出力項目の情報が表示されます。
QGraphicsItem(0x161015c8, pos=0,0)
1.2 ビュー(ビュー)
QGraphicsView は、シーンのコンテンツを視覚化するために使用されるビュー ウィジェットを提供します。複数のビューを同じシーンに接続して、同じデータセットに複数のビューポートを提供できます。 |
以下は QGraphicsView の一般的に使用される関数の一部です::
- ビュー コンポーネントは、大きなシーンを参照するためのスクロール バーを提供するスクロール可能な領域です。 QGraphicsView::SCrollHandDrag をパラメータとして setDragMode() 関数を使用して、カーソルを手のひらの形に変更し、シーンをドラッグできるようにします。
- setDragMode() のパラメーターが QGraphicsView::RubberBandDrag に設定されている場合、マウスを使用してビュー上のラバー バンド フレームをドラッグしてグラフィック項目を選択できます。
- デフォルトの QGraphicsView は、ビューポート コンポーネントとして QWidget を提供します。植栽に OpenGL を使用したい場合は、QGraphicsView::setViewport() を呼び出して、QOpenGLWidget をビューポートとして設定できます。QGraphicsView はビューポート ウィジェットの所有権を取得します。
前のプログラムでは、最初にヘッダー ファイル # include <QGraphicsView> を追加し、続いて main 関数のコードの "return app.exec();" 行の前に次のコードを追加します。
//为场景创建视图
QGraphicsView view(&scene);
//设置场景的前景色
view.setForegroundBrush(QColor(255, 255, 0, 100));
//设置场景的背景图片
view.setBackgroundBrush(QPixmap("../myScene/background.png"));
view.resize(400, 300);
view.show();
ここでは、新しいビューコンポーネントを作成し、視覚化するシーンを指定します。次に、ビューのシーンの前景色と背景イメージを設定します。シーンは、グラフィック アイテム レイヤー (ItemLayer)、前景レイヤー (ForegroundLayer)、背景レイヤー (BackgroundLayer) の 3 つのレイヤーに分割されます。シーンの描画は常にバックグラウンド レイヤから始まり、次にグラフィックス アイテム レイヤ、最後にフォアグラウンド レイヤとなります。グラデーションやテクスチャを使用するなど、前景レイヤーと背景レイヤーの両方を QBrush で塗りつぶすことができます。ここでは前景色は半透明の黄色に設定されていますが、もちろん他の塗りつぶしに設定することもできます。実際、適切な前景色を使用すると、半透明の黒を使用して夕暮れの効果を実現するなど、多くの特殊効果を実現できることに注意してください。
このコードは、QGraphicsView クラスの関数を使用して、シーンの背景と前景を設定します。実際、QGraphicsScene の同じ名前の関数を使用して実装することもできますが、それらの効果はまったく同じではありません。シーンの背景または前景が QGraphicsScene オブジェクトを使用して設定されている場合、それはシーンに関連付けられたすべてのビューに対して有効ですが、QGraphicsView オブジェクトによって設定されたシーンの背景または前景は、対応するビューに対してのみ有効です。
プログラムを実行すると、その効果が次の図に示されます。ビューの中央部分に長方形のグラフィックアイテムと背景画像が描画されていることがわかりますが、この問題については後の座標系で詳しく説明します。
1.3 グラフィックアイテム
QGraphicsItem は、シーン内のグラフィックス項目の基本クラスです。グラフィックスビューフレームワークは、四角形 (QGraphicsRectlem)、楕円 (QGraphicsEllipseltem)、テキスト項目 (QGraphicsTextltem) などの典型的な形状の標準グラフィックス項目を提供します。ただし、QGraphicsItem の強力な機能は、カスタム グラフィックス項目を作成する場合にのみ使用できます。 |
QGraphicsItem は主に次の機能をサポートします。
- マウスダウン、移動、リリース、ダブルクリック、ホバー、ホイール、および右クリックのメニュー イベント。
- キーボード入力フォーカスとキーボード イベント。
- ドラッグアンドドロップイベント;
- QGraphicsItemGroup を使用して親子関係を通じてグループ化を実現します。
- 衝撃チェック。
さらに、グラフィック アイテムにはカスタム データを保存することもできます。setData() を使用してデータを保存し、data() を使用してデータを取得することができます。以下のカスタムグラフィックアイテム。
前のプログラムに新しいファイルを追加し、テンプレートとして C++ クラスを選択します。クラス名は Myltem、基本クラスは QGraphicsItem、タイプ情報は「なし」を選択します。追加が完了したら、myitem.h ファイルに 2 つの関数宣言を追加します。
#ifndef MYITEM_H
#define MYITEM_H
#include <QGraphicsItem>
class MyItem : public QGraphicsItem
{
public:
MyItem();
//返回要绘制图形项的矩形区域
QRectF boundingRect() const;
//用来执行实际的绘图操作
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget);
};
#endif // MYITEM_H
次に、ヘッダー ファイル # include <QPainter> を myitem.cpp ファイルに追加し、追加された 2 つの関数を定義します。
#include "myitem.h"
#include <QPainter>
MyItem::MyItem()
{
}
//返回要绘制图形项的矩形区域
QRectF MyItem::boundingRect() const
{
qreal penWidth = 1;
return QRectF(0 - penWidth / 2, 0 - penWidth / 2,
20 + penWidth, 20 + penWidth);
}
//用来执行实际的绘图操作
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
Q_UNUSED(option); //标明该参数没有使用
Q_UNUSED(widget);
painter->setBrush(Qt::red);
painter->drawRect(0, 0, 20, 20);
}
カスタムグラフィックアイテムを実装するには、最初にQGraphicsItemのサブクラスを作成し、次にその2つの純粋な仮想パブリック関数であるboimdingRect()とpaint()を再実装します。前者はグラフィックアイテムを描画するための長方形領域を返すために使用され、後者は実際の描画操作を実行するために使用されます。このうち、 boimdingRect() 関数は、グラフィックス項目の外側の境界を四角形として定義し、すべての描画操作はグラフィックス項目の境界四角形に限定される必要があります。さらに、QGraphicsView はこの四角形を使用して目に見えないグラフィックス項目を削除する必要があり、QGraphicsItem の衝突検出メカニズムもこの境界四角形を使用する必要があります。
次に、#include "myitem.h" を main.cpp に追加し、前のグラフィック項目の定義ステートメントを次のように変更します。
MyItem *item = new MyItem;
この時点でプログラムを実行すると、次の図のような効果が得られます。カスタムの赤い四角形がビューの中央に表示され、背景画像の位置も変更されていることがわかります。これらの問題については、次の座標系で説明します。単純なグラフィックス項目を追加するだけの場合は、グラフィックス ビュー フレームワークが提供する 8 つの標準グラフィックス項目を直接使用することもできます。
以下は、グラフィックス ビュー フレームワークのイベント配信の図です。
2. グラフィックスビューフレームの座標系
グラフィックス ビュー フレームワークはデカルト座標系に基づいており、シーン内のグラフィックス アイテムの位置とジオメトリは x 座標と y 座標で表されます。変換されていないビューでシーンを表示する場合、シーン内のセルは画面上のピクセルを表します。グラフィックス ビュー フレームには、グラフィックス アイテム座標、シーン座標、ビュー座標という 3 つの座標系が有効です。アプリケーションの利便性を考慮して、3 つの座標系間のマッピングを完了するために、グラフィックス ビュー フレームワークにはいくつかの便利な関数が提供されています。描画時、シーン座標は QPainter の論理座標に対応し、ビュー座標はデバイス座標に対応します。
2.1 シーン座標
シーン座標は、すべてのグラフィックス項目の基本座標系です。シーン座標系は、すべてのトップレベルのグラフィック項目の位置を記述し、ビューからシーンに渡されるすべてのイベントの基礎を形成します。シーン座標の原点はシーンの中心にあり、x 軸の正の方向は右、y 軸の正の方向は下です。 |
シーン内の各グラフィック アイテムには、グラフィック アイテムのローカル座標と境界四角形に加えて、シーン座標 (QGraphicsItem::scenePos()) とシーン内の境界四角形 (QGraphicsItem::sceneBoundingRect()) があります。シーン座標は、シーン座標系におけるグラフィック項目の位置を記述するために使用され、グラフィック項目のシーン境界四角形は、シーン内のどの領域が変更されたかを判断するために QGraphicsScene によって使用されます。
QGraphicsScene クラスの座標系は、以下の図に示すように、中心を原点 (0,0) とします。
2.2 ビュー座標
ビューの座標はウィジェットの座標です。ビュー座標の各単位はピクセルに対応します。QGraphicsView ビューの左上隅は (0,0) で、x 軸の正の方向は右、y 軸の正の方向は下です。 |
すべてのマウス イベントは、最初はビュー座標を使用します。QGraphicsView クラスは QWidget クラスを継承するため、図に示すように、他の QWidget クラスと同様に、ウィンドウの左上隅を独自の座標系の原点として使用します。
2.3 グラフィックアイテムの座標
グラフィックス アイテムは独自のローカル座標を使用します。この座標系は通常、グラフィックス アイテムの中心に原点を持ち、すべての変換の原点でもあります。グラフィックアイテムの座標方向は、右がx軸の正方向、下がy軸の正方向となります。グラフィックス項目を作成した後は、グラフィックス項目の座標に注意するだけでよく、QGraphicsScene と QGraphicsView がすべての変換を完了します。 |
QGraphicsItem クラスの座標系。QGraphicsItem クラスのPaint()関数が描画要素を再描画するために呼び出される場合、次の図に示すように、この座標系が参照として使用されます。
2.4 座標マッピング
シーン内のグラフィック アイテムを操作する場合、これらの座標変換は、座標または任意の形状をシーンからグラフィック アイテムに、またはあるグラフィック アイテムから別のグラフィック アイテムに、またはビューからシーンにマッピングするのに役立ちます。例えば:
- QGraphicsView のビューポート上でマウスをクリックすると、QGraphicsView::mapToScene() および QGraphicsScene::itemAt() を呼び出して、カーソルの下にあるグラフィック項目を取得できます。
- ビューポート内のグラフィック項目の位置を取得したい場合は、最初にグラフィック項目に対して QGraphicsItem::mapToScene() を呼び出し、次にビューに対して QGraphicsView::mapFromScene() を呼び出すことができます; ビュー内の楕円に含まれるグラフィック項目を取得したい場合は、まず QPainterPath オブジェクトをパラメータとして mapToScene() 関数に渡し、次にマップされたパスを QGraphicsScene::items() に渡すことができます。機能。
座標マッピングは、ビュー、シーン、グラフィック アイテム間だけでなく、子グラフィック アイテムと親グラフィック アイテム間、またはグラフィック アイテムとグラフィック アイテム間でも使用できます。グラフィックス ビュー フレームワークによって提供されるすべてのマッピング関数を以下の表に示します。すべてのマッピング関数は、点、四角形、多角形、およびパスをマッピングできます。
マッピング関数 |
変換タイプ |
QGraphicsView::mapToScene() |
シーンへのビュー |
QGraphicsView::mapFromScene() |
見るべきシーン |
QGraphicsItem::mapFromScene() |
シーンからグラフィックアイテムへ |
QGraphicsItem::mapToScene() |
グラフィックアイテムをシーンに |
QGraphicsItem::mapToParent() |
子グラフィックアイテムから親グラフィックアイテムへ |
QGraphicsItem::mapFromParent() |
親シェイプ項目から子シェイプ項目へ |
QGraphicsItem::mapToItem() |
このグラフィック アイテムを他のグラフィック アイテムに |
QGraphicsItem::mapFromItem() |
このグラフィック アイテムの他のグラフィック アイテム |
ブログガーデン(fengMisaka)から記事を転送しました:Qt 2D描画その5:グラフィックスビューフレームの構造と座標系
この記事のメリット、Qt 開発学習教材パッケージの受け取り料金、技術ビデオ、コンテンツには (C++ 言語基礎、Qt プログラミング入門、QT シグナルとスロットのメカニズム、QT インターフェイス開発イメージ図、QT ネットワーク、QT データベース プログラミング、QT プロジェクト戦闘、QSS、OpenCV、Quick モジュール、インタビューの質問など) ↓↓↓↓↓↓ 下記を参照