2011-01-20 6 views
18

Tôi hiện có thể tải hình ảnh của tôi vào một cảnh grahpics, và sau đó lại vào QGraphicsViewer.cách xoay hình ảnh trong QGraphicsView

Tôi có thể triển khai tính năng thu phóng bằng cách xác định QEvent :: Wheel và sau đó gọi hàm scale() của graphicsViews.

Tuy nhiên, tôi dường như không thể tìm ra cách để chức năng pan hoạt động. Về cơ bản tôi muốn phát hiện khi một con chuột đã nhấp vào hình ảnh, và sau đó di chuyển hình ảnh sang trái, phải, lên hoặc xuống cùng với con chuột.

Hiện tại, về cơ bản, tôi có lớp MouseFilter đang phát hiện sự kiện và thực hiện những việc khác nhau tùy thuộc vào loại sự kiện. Tôi gắn trình lắng nghe đó vào đối tượng QGraphicsView

Trả lời

11

QGraphicsView có hỗ trợ panning chuột tích hợp. Đặt chính xác DragMode và nó sẽ xử lý phần còn lại. Bạn cần bật thanh cuộn để hoạt động.

+0

Bạn có nghĩ rằng tôi có thể tự thực hiện việc này không? Tôi muốn làm điều này trên nút chuột phải. Làm cách nào để cuộn chế độ xem từ mã? – neuviemeporte

+0

@neuviemeporte: Tôi không biết làm thế nào để làm điều đó với nhấp chuột phải. Bạn có thể muốn đăng nó như một câu hỏi riêng biệt để người khác có thể trả lời câu hỏi đó. –

+0

Bạn không còn phải bật thanh cuộn trong Qt 5.0 – vsz

39

Trong trường hợp ai đó đang tự hỏi làm thế nào để làm điều đó một mình, nó thực sự khá đơn giản. Dưới đây là các mã từ ứng dụng của tôi:

class ImageView : public QGraphicsView 
{ 
public: 
    ImageView(QWidget *parent); 
    ~ImageView(); 

private: 
    virtual void mouseMoveEvent(QMouseEvent *event); 
    virtual void mousePressEvent(QMouseEvent *event); 
    virtual void mouseReleaseEvent(QMouseEvent *event); 

    bool _pan; 
    int _panStartX, _panStartY; 
}; 

Bạn cần lưu trữ vị trí bắt đầu của kéo, ví dụ như thế này (tôi đã sử dụng các nút bên phải):

void ImageView::mousePressEvent(QMouseEvent *event) 
{ 
    if (event->button() == Qt::RightButton) 
    { 
     _pan = true; 
     _panStartX = event->x(); 
     _panStartY = event->y(); 
     setCursor(Qt::ClosedHandCursor); 
     event->accept(); 
     return; 
    } 
    event->ignore(); 
} 

Ngoài ra, bạn cần phải rõ ràng cờ và khôi phục con trỏ khi nút được giải phóng:

void ImageView::mouseReleaseEvent(QMouseEvent *event) 
{ 
    if (event->button() == Qt::RightButton) 
    { 
     _pan = false; 
     setCursor(Qt::ArrowCursor); 
     event->accept(); 
     return; 
    } 
    event->ignore(); 
} 

Để thực sự quản lý thao tác kéo, bạn cần ghi đè sự kiện di chuyển chuột. QGraphicsView thừa hưởng một QAbstractScrollArea và các thanh cuộn của nó có thể dễ dàng truy cập. Bạn cũng cần cập nhật vị trí xoay:

void ImageView::mouseMoveEvent(QMouseEvent *event) 
{ 
    if (_pan) 
    { 
     horizontalScrollBar()->setValue(horizontalScrollBar()->value() - (event->x() - _panStartX)); 
     verticalScrollBar()->setValue(verticalScrollBar()->value() - (event->y() - _panStartY)); 
     _panStartX = event->x(); 
     _panStartY = event->y(); 
     event->accept(); 
     return; 
    } 
    event->ignore(); 

} 
+0

chỉ đơn giản là rực rỡ –

+0

Cảm ơn bạn đã viết mã, rất hữu ích! – enriched

+0

vâng, chính xác những gì tôi đang tìm kiếm..even năm sau, cảm ơn! – Amazonasmann

2

giải pháp neuviemeporte yêu cầu phải phân lớp QGraphicsView.

Có thể có được một triển khai kéo hoạt động khác mà không cần phân lớp chế độ xem bằng cách sử dụng eventFilter. Nếu bạn không cần tùy chỉnh các hành vi khác của QGraphicsView, kỹ thuật này sẽ giúp bạn tiết kiệm một số công việc.

Giả sử logic GUI của bạn được duy trì bởi lớp con QMainWindow và QGraphicsView & QGraphicsScene được khai báo là một thành viên riêng tư của lớp con này. Bạn sẽ phải thực hiện các chức năng eventFilter như sau:

bool MyMainWindow::eventFilter(QObject *obj, QEvent *event) 
{ 
    if (obj == scene && event->type() == Event::GraphicsSceneMouseMove) 
    { 
     QGraphicsSceneMouseEvent *m = static_cast<QGraphicsSceneMouseEvent*>(event); 
     if (m->buttons() & Qt::MiddleButton) 
     { 
      QPointF delta = m->lastScreenPos() - m->screenPos(); 
      int newX = view->horizontalScrollBar()->value() + delta.x(); 
      int newY = view->verticalScrollBar()->value() + delta.y(); 
      view->horizontalScrollBar()->setValue(newX); 
      view->verticalScrollBar()->setValue(newY); 
      return true; 
     } 
    } 

    return QMainWindow::eventFilter(obj, event); 
} 

Để lọc các sự kiện từ QGraphicsScene, bạn sẽ phải cài đặt MyMainWindow như một eventFilter của cảnh. Có lẽ bạn có thể làm điều này trong cùng một chức năng mà bạn thiết lập GUI của bạn.

void MyMainWindow::setupGUI() 
{ 
    // along with other GUI stuff... 

    scene->installEventFilter(this); 
} 

Bạn có thể mở rộng ý tưởng này để thay thế con trỏ bằng cách kéo "tay" như được hiển thị trước đó.