6

スロット呼び出しscrollHorizo​​ntal(int dx)を実装するQGraphicsViewから派生したカスタムクラスがあります。コード内は単純です

void CustomView::scrollHorizontal(int dx){
    scrollContentsBy(dx, 0);
}

私の問題は、このようなスクロールは機能しますが、シーンを適切に更新しないことです。代わりに、アイテムのpaint()メソッドを新たに呼び出す代わりに、ビューの端にあるピクセルが繰り返されます。

後で電話をかけてみましupdate()たが、何も起こりません。ドラッグしてスクロールを有効にしてみましたが、更新は正常に機能します! しかし、私はそれをプログラムで行う必要があり、スクロールバーが非表示になっているためhorizontalScrollBar()->setValue()、ビューをスクロールしないようにします。

私も試しました:

scrollContentsBy(dx, 0);
this->scene()->invalidate(sceneRect());
this->update();

アップデート:

QPointF center = mapToScene(viewport()->rect().center()); 
centerOn(center.x() - dx, center.y()); 
update(); 

動作していますが、トップビューのスクロールがボトムビューよりも遅くなりました。これは新しい問題です。それらはsignals とslots にリンクされており、下のビューでscrollContentsBy(int dx, int dy)オーバーライドしましたemit horizontalScroll(dx)。これはslot、上図で捉えたものです。

スクロールが異なる速度で発生する理由はありますか? スクロールバーがボトムビューの一部であり、効果的に「小さい」ウィンドウになっていることに関係している可能性がありますか?

更新 2:

スクロール速度が異なるのは、 を使用して整数ベースの「中心」を与えるために丸めが発生したことに起因しているようですmapToScene(viewport()->rect().center());

これを回避する方法はありますか?浮動小数点の中心点を取得する方法がわかりません。

更新 3:

だから私はこれをほとんど解決しました.mapToSceneが必要であることがわかりました(ウェブ上の他の場所で見つけたコード)。

ビューポートの FP 計算された中心を保存することでこれを修正しました。これQPointFで、2 つのビューをスクロールするときのエラーの量は目立たなくなりました。

最後の問題は、右にいくらかスクロールし、ウィンドウのサイズを変更してから再度スクロールすると、ビューが整列しなくなることです。これは、中心点が計算されたときとセンタリングが行われたときの論理的な順序付けと関係があると思います。

QGraphicsScene::ResizeEvent()現在、必要に応じてセンターを更新する次のコードスニペットを使用しています。

QRectF viewPort(viewport()->rect());
QPointF rectCenter((viewPort.x() + viewPort.x() + viewPort.width())/2.0, (viewPort.y() + viewPort.y() + viewPort.height())/2.0);

viewCenter = rectCenter;

と私horizontalScroll(int dx) slot

void CustomView::horizontalScroll(int dx)
{
    viewCenter.setX(viewCenter.x() - dx);
    centerOn(viewCenter.x(), viewCenter.y());
    update();
}

ウィンドウのサイズを変更すると、2 つのビューの配置が崩れる問題を修正するにはどうすればよいですか? さらに明確にする必要がある場合は、お尋ねください.

更新 4:

ラフコード スケルトン

Class HeaderView:

class HeaderView View : public QGraphicsView
{
    Q_OBJECT
public:
    HeaderView(QWidget * parent = 0);
    HeaderView(QGraphicsScene * scene, QWidget * parent = 0);

private:
    QPointF viewCenter;

protected:
    void resizeEvent ( QResizeEvent * event );

public slots:
    void horizontalScroll(int);
    void addModel(qreal, qreal, const QString&);

};

HeaderView.cpp

void HeaderView::resizeEvent(QResizeEvent *event)
{
    QGraphicsView::resizeEvent(event);
    QRectF viewPort(viewport()->rect());
    QPointF rectCenter((viewPort.x() + viewPort.x() + viewPort.width())/2.0, (viewPort.y() + viewPort.y() + viewPort.height())/2.0);

    viewCenter = rectCenter;
}

void HeaderView::horizontalScroll(int dx)
{
    viewCenter.setX(viewCenter.x() - dx);
    centerOn(viewCenter.x(), viewCenter.y());
    update();
}

クラス EventView:

class EventView : public QGraphicsView
{
Q_OBJECT
public:
    EventView(QWidget * parent = 0);
    EventView(QGraphicsScene * scene, QWidget * parent = 0);
    QRectF visibleRect();

protected:
     void scrollContentsBy ( int dx, int dy );

signals:
    void horizontalScroll(int);

};

EventView.cpp

void EventView::scrollContentsBy(int dx, int dy)
{
    QGraphicsView::scrollContentsBy(dx, dy);

    if(dx != 0){
        emit horizontalScroll(dx);
    }
}

クラス MainWindow のどこか:

connect(eventView, SIGNAL(horizontalScroll(int)), headerView, SLOT(horizontalScroll(int));
4

3 に答える 3

10

私は Qt 4.6.3 - 4.7.2 で作業しており、次の方法でそれぞれを使用できるQGraphicsViewと主張する必要があります。QScrollBar

//graphics view initialization
QGraphicsView *graphicsView = new QGraphicsView(parent);
QGraphicsScene *scene = new QGraphicsScene(0,0,widthOfScene,heightOfScene,parent);
graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
graphicsView->setScene(scene);

//in another method
QScrollBar* yPos=graphicsView->verticalScrollBar();
yPos->setValue((int) newValue);

それらが隠されているかどうかは問題ではありません。setValue(int)グラフィックス ビューよりも大きいグラフィックス シーンがある限り、それらは引き続き応答します。

は、スクロールバーを適切な位置に移動する にQGraphicsViewも応答します。ensureVisible

于 2012-07-20T17:02:13.420 に答える
3

ここで説明されているように呼び出すことは想定されていませんscrollContentsBy: http://qt-project.org/doc/qt-4.8/qabstractscrollarea.html#scrollContentsBy

非表示のスクロールバーを呼び出してスクロールできるかどうかはわかりません。そうでない場合 translateは、オプションです。

于 2012-07-17T18:22:41.600 に答える
2

スクロールバーを使用しようとしましたか? それらを非表示にしても、それらが存在しなくなるわけではなく、ドキュメントにはQScrollBar::setValue、特定の位置までスクロールするために使用する必要があると記載されています。

別のオプションはQGraphicsView::centerOn(QPointF)、現在の中心点と組み合わせて使用​​することです-あなたも試したように-ただし、メソッド内で中心点を直接計算します(中心点を事前に計算して保存しないでください) QGraphicsView::mapToScene(int,int):

void CustomView::horizontalScroll(int dx)
{
    QPointF viewCenter = mapToScene(width() / 2, height() / 2);
    viewCenter += QPointF(dx, 0); // Why did you subtract instead of add dx?
    centerOn(viewCenter); // BTW, you don't need to do .x(), .y()
    // You can remove update(); as this is already called in centerOn().
}

あなたが言ったように、「scrollContentsBy(int dx, int dy)オーバーライドされたemit horizontalScroll(dx)」場合は、スーパークラスメソッドを呼び出して、ビュー自体をスクロールできるようにする必要があることに注意してください。

void CustomView::scrollContentsBy(int dx, int dy)
{
    emit horizontalScrolled(dx); // (You should call it different than the slot!)
    QGraphicsView::scrollContentsBy(dx, dy); // <-- This is what I mean!
}
于 2012-07-19T21:41:06.367 に答える