2016-11-18 12 views
1

렌더링 된 이미지를 보여주는 미리보기를 만들었습니다. 확대 기능에 Image Viewer Example을 사용했습니다. 따라서 이미지를 표시 할 수있는 QScrollArea을 상속하는 클래스가 있고 QLabel에 있고 특정 제한으로 확대/축소/맞추기가 가능합니다. 나는 필요에 따라 스크롤바를 보여 주었다.QScrollArea의 이미지 확대 및 패닝

새로운 요구 사항으로, 나는 패닝 할 수 있어야하며, 은 스크롤바을 보여주지.

나는 그것을 할 수있는 방법을 찾고 있었고 - 이미지의 한 점을 스크롤바에 연결하기 위해 마우스 누름, 이동 및 놓기 이벤트를 사용하는 사람이 examples 인 것을 발견했습니다.
문제점 : 스크롤바가 보이지 않는 경우
1) 움직임의 방향은, 예기치 않은 - 그 마우스의 방향으로 마우스에서 (체류)를 이동 객체 패닝, 스크롤바가 반대 방향으로 이동하면서
2) 나는 움직임이 스크롤바 크기로 제한되어 있다고 생각한다 ... 만약 내가 역방향 움직임을 계산한다면 벽을 치고 한 방향으로 움직일 공간이 남아있다.
3) 이것은 확대와 함께 작동하지 않을 것이다. 패닝이 필요합니다. 더 복잡한 계산이 필요할 것입니다.

나는 교대 QGraphicsView 사용할 수 있으며,

setDragMode(ScrollHandDrag); 

그것은뿐만 아니라 확대와 함께 좋은 일 것이고, 내가 직접 구현할 필요가 없습니다 것입니다.
내가 아직 수행하지 않은 이유는 QGraphicsScene도 추가해야하고, 원하는 이미지가 포함 된 QGraphicsPixmapItem을 추가해야합니다. 그런 다음 패닝 이외의 모든 마우스 이벤트를 비활성화하는 방법을 찾고 여전히 QScrollArea을 사용합니다. QGraphicsView;
오버 헤드가 너무 많습니다 (속도와 메모리가 거의없는 임베디드 장치의 경우 매우 가볍습니다).

어떤 옵션이 가장 좋습니까? 가능한 한 가벼운 무게로 뷰어에서 확대 된 이미지를 팬 할 수있는 방법이 있습니까?

답변

2

사용자 정의 줌이와 화면 이동이 가능한 픽스맵 뷰어에 대한 paintEvent 구현 5 개 라인 긴 점을 감안, 하나는뿐만 아니라 처음부터 구현할 수 :

// https://github.com/KubaO/stackoverflown/tree/master/questions/image-panzoom-40683840 
#include <QtWidgets> 
#include <QtNetwork> 

class ImageViewer : public QWidget { 
    QPixmap m_pixmap; 
    QRectF m_rect; 
    QPointF m_reference; 
    QPointF m_delta; 
    qreal m_scale = 1.0; 
    void paintEvent(QPaintEvent *) override { 
     QPainter p{this}; 
     p.translate(rect().center()); 
     p.scale(m_scale, m_scale); 
     p.translate(m_delta); 
     p.drawPixmap(m_rect.topLeft(), m_pixmap); 
    } 
    void mousePressEvent(QMouseEvent *event) override { 
     m_reference = event->pos(); 
     qApp->setOverrideCursor(Qt::ClosedHandCursor); 
     setMouseTracking(true); 
    } 
    void mouseMoveEvent(QMouseEvent *event) override { 
     m_delta += (event->pos() - m_reference) * 1.0/m_scale; 
     m_reference = event->pos(); 
     update(); 
    } 
    void mouseReleaseEvent(QMouseEvent *) override { 
     qApp->restoreOverrideCursor(); 
     setMouseTracking(false); 
    } 
public: 
    void setPixmap(const QPixmap &pix) { 
     m_pixmap = pix; 
     m_rect = m_pixmap.rect(); 
     m_rect.translate(-m_rect.center()); 
     update(); 
    } 
    void scale(qreal s) { 
     m_scale *= s; 
     update(); 
    } 
    QSize sizeHint() const override { return {400, 400}; } 
}; 

대등 한 QGraphicsView 기반의 위젯이 약간 짧은 것, 픽스맵이 매우 작 으면 오버 헤드가 약간 더 커집니다. 큰 픽스맵의 경우 픽스맵을 렌더링하는 데 걸리는 시간이 QGraphicsScene/QGraphicsView 기기로 인한 오버 헤드를 크게 초과합니다. 결국 씬 자체는 정적이며, 이는 성능을위한 이상적인 동작 포인트 인 QGraphicsView입니다.

class SceneImageViewer : public QGraphicsView { 
    QGraphicsScene m_scene; 
    QGraphicsPixmapItem m_item; 
public: 
    SceneImageViewer() { 
     setScene(&m_scene); 
     m_scene.addItem(&m_item); 
     setDragMode(QGraphicsView::ScrollHandDrag); 
     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 
     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 
     setResizeAnchor(QGraphicsView::AnchorViewCenter); 
    } 
    void setPixmap(const QPixmap &pixmap) { 
     m_item.setPixmap(pixmap); 
     auto offset = -QRectF(pixmap.rect()).center(); 
     m_item.setOffset(offset); 
     setSceneRect(offset.x()*4, offset.y()*4, -offset.x()*8, -offset.y()*8); 
     translate(1, 1); 
    } 
    void scale(qreal s) { QGraphicsView::scale(s, s); } 
    QSize sizeHint() const override { return {400, 400}; } 
}; 

그리고 테스트 장치 :

int main(int argc, char *argv[]) 
{ 
    QApplication a{argc, argv}; 
    QWidget ui; 
    QGridLayout layout{&ui}; 
    ImageViewer viewer1; 
    SceneImageViewer viewer2; 
    QPushButton zoomOut{"Zoom Out"}, zoomIn{"Zoom In"}; 
    layout.addWidget(&viewer1, 0, 0); 
    layout.addWidget(&viewer2, 0, 1); 
    layout.addWidget(&zoomOut, 1, 0, 1, 1, Qt::AlignLeft); 
    layout.addWidget(&zoomIn, 1, 1, 1, 1, Qt::AlignRight); 

    QNetworkAccessManager mgr; 
    QScopedPointer<QNetworkReply> rsp(
       mgr.get(QNetworkRequest({"http://i.imgur.com/ikwUmUV.jpg"}))); 
    QObject::connect(rsp.data(), &QNetworkReply::finished, [&]{ 
     if (rsp->error() == QNetworkReply::NoError) { 
      QPixmap pixmap; 
      pixmap.loadFromData(rsp->readAll()); 
      viewer1.setPixmap(pixmap); 
      viewer2.setPixmap(pixmap); 
     } 
     rsp.reset(); 
    }); 
    QObject::connect(&zoomIn, &QPushButton::clicked, [&]{ 
     viewer1.scale(1.1); viewer2.scale(1.1); 
    }); 
    QObject::connect(&zoomOut, &QPushButton::clicked, [&]{ 
     viewer1.scale(1.0/1.1); viewer2.scale(1.0/1.1); 
    }); 
    ui.show(); 
    return a.exec(); 
}