2016-09-29 8 views
2

2つのQDeclarativeItemがあります。 ForegroundLayer上での描画QMLQtはバックグラウンドアイテムにペイントイベントを伝播します

Rectangle { 
    width: 1920 
    height: 1080 

    BackgroundLayer{ 
     id: background_layer 
     anchors.fill: parent 
    } 

    ForegroundLayer { 
     id: foreground_layer 
     anchors.fill: parent 
    } 
} 

void BackgroundLayer::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) 
{ 
    painter->drawImage(QRectF(dx1, dy1, dx2-dx1, dy2-dy1), shownImage, QRectF(sx1, sy1, sx2-sx1, sy2-sy1)); 
} 

void ForegroundLayer::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) 
{ 
    QPen pen(Qt::red, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); 
    painter->setPen(pen); 
    painter->drawLine(p1, p2); 
} 

は、それが画像全体を再描画させる、BackgroundLayerペイントイベントをトリガします。結果として、描画が遅くなります。これを避け、本当に必要なときにのみイメージを再描画することは可能ですか?

+0

WA_OpaquePaintEventとWA_TranslucentBackgroundは(何らかの理由で)少し速くなりますが、イメージはまだ再描画されます。これは動作しません。 –

+0

'Rectangle {children:[}}'に 'BackgroundLayer'と' ForegroundLayer'を入れた場合どうなりますか – UmNyobe

+0

'Rectangle {children:[}} 'の変更はありません –

答えて

1

なぜ他の種類の動作が期待されますか? Qtはすべての宣言的項目の画像を保持しません。メモリの面では非常に高価です。ただし、これを有効にするオプションがあります。おそらくそうするべきです。詳しくはcacheModeのドキュメントをご覧ください。

アイテムを更新する必要があるときは、の更新矩形と下位のすべてを、下から上のZ順に再塗りつぶしする必要があります。 QGraphicsViewの下にウィジェットがあり、ビュー自体が半透明であれば、これらのウィジェットも同様に再描画する必要があります。

アップデートが必要な領域を正確に知っている場合は、その知識を使用する必要があります。QGraphicsItem::update(const QRectF &)を呼び出して、更新が必要な領域の範囲を示します。それ以外の場合は、ヌルの長方形で、更新領域はアイテム全体にまたがります。

QGraphicsViewupdateModeMinimalViewportUpdateに設定されていることも確認してください。

QGraphicsItemすべてのインスタンスとすべてのQWidgetインスタンスはすべて、内部のQImageにペイントされ、その後、元のネイティブウィンドウにblittedまたはスワップされます。彼らは背中合わせのZオーダーでペイントし、スキップされる唯一のウィジェットまたはアイテムは、不透明なウィジェットまたはアイテムの下に完全に含まれるものです。

+0

はい、そうですが、方法はありません私は全体の画像を再描画する必要はないので、少なくとも描画エリアを制限するには?私はsetClipRect()について知っており、解決策ではありません。もし私がf.ex.左上から右下隅に対角線を描くと、画面全体が再描画されますが、実際にはそれが少ししか変更されません。 –

+0

編集を参照してください....... –

1

短い答え:ちょうどQPixmapshownImage

void BackgroundLayer::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) 
{ 
    painter->drawPixmap(QRectF(dx1, dy1, dx2-dx1, dy2-dy1), shownPixmap, QRectF(sx1, sy1, sx2-sx1, sy2-sy1)); 
} 

説明から一度に変換使用:画面上

塗装ピックスマップは画像よりもはるかに高速です。他の選択肢は機能しないか、あまりに複雑すぎます。

ペイントイベントは、上部ウィジェットから子に再帰的に伝播します。 基本的にQtにはペイントする矩形が与えられ、この矩形の中のすべてのウィジェットはペイントイベントを受け取ります。

私は私はあなたがForegroundLayerから古い塗装アーティファクトをせずにここでそれを行うことができますどのように見ることができない何を達成したいことはウィジェットの属性をハッキングして、いくつかの具体的な例でなんとかなるかもしれません確信しているが、

たとえば、2行あるとします。ABCDです。

  • だけP1後行AB
  • を見たいと思ってペイントする最初の呼び出しの後、p2はあなただけ見てからあなたを防ぐためにラインCD

を見たいと思って更新されましたCD、Qt を塗りつぶしたときの線ABは、塗りつぶされている矩形の背景全体をクリアする必要があります。なんらかの理由でBackgroundLayerがペイントしない場合、背景イメージは消えます。