我想实现一个基于C++ Qt的图形视图的自由拖动功能。
但是,我需要在不更改sceneRect
和不使用view->setDragMode(QGraphicsView::ScrollHandDrag)
的情况下实现这一点,因为我的一些业务逻辑依赖于sceneRect
进行计算。
下面的代码可以重现我目前面临的问题,同时仍然成功运行。
view.h:
#include <QGraphicsView>
#include <QMouseEvent>
#include <QWheelEvent>
#include <qscrollbar.h>
class CView : public QGraphicsView
{
Q_OBJECT
public:
CView(QWidget* parent = nullptr) : QGraphicsView(parent) {
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
setResizeAnchor(QGraphicsView::AnchorUnderMouse);
}
protected:
void mousePressEvent(QMouseEvent* event) override {
if (event->button() == Qt::LeftButton) {
m_lastPos = event->pos();
}
QGraphicsView::mousePressEvent(event);
}
void mouseMoveEvent(QMouseEvent* event) override {
if (event->buttons() & Qt::LeftButton) {
QPoint delta = event->pos() - m_lastPos;
QRectF sceneRect = this->sceneRect();
sceneRect.translate(-delta);
this->setSceneRect(sceneRect);
ensureVisible(sceneRect);
m_lastPos = event->pos();
}
QGraphicsView::mouseMoveEvent(event);
}
void wheelEvent(QWheelEvent* event) override {
QPoint scrollAmount = event->angleDelta();
double scaleFactor = 1.15;
if (scrollAmount.y() > 0) {
scale(scaleFactor, scaleFactor);
}
else if (scrollAmount.y() < 0) {
scale(1.0 / scaleFactor, 1.0 / scaleFactor);
}
// QRectF sceneRect = this->sceneRect();
// QPointF viewCenter = mapToScene(viewport()->rect().center());
// sceneRect.moveCenter(viewCenter);
// this->setSceneRect(sceneRect);
event->accept();
}
private:
QPoint m_lastPos;
};
场景h:
#include <QObject>
#include <QGraphicsScene>
class CScene : public QGraphicsScene
{
Q_OBJECT
public:
CScene() {}
protected:
void drawBackground(QPainter *painter, const QRectF &rect) override {
QGraphicsScene::drawBackground(painter, rect);
painter->fillRect(sceneRect(), Qt::black);
}
};
main.cpp:
#include "View.h"
#include "Scene.h"
#include <QApplication>
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
CView* view = new CView;
view->resize(600, 500);
CScene* scene = new CScene;
scene->setSceneRect(0, 0, 300, 200);
view->setScene(scene);
view->show();
return a.exec();
}
我遇到了两个问题:
- 当我开始拖动鼠标时,视图会跳转(我注意到如果滚动条没有隐藏,它们的值就会变成最大值。我不确定这是由于坐标问题还是因为我在
mouseMoveEvent
中添加了ensureVisible(sceneRect)
)。 - 如果我将视图嵌入到一个小部件中,并在小部件中放置一个
QPushButton
,当我单击按钮并调用view->fitInView(sceneRect, Qt::KeepAspectRatio)
时,场景的位置不在视图的中心。
1条答案
按热度按时间yh2wf1be1#
我已经找出了问题的根源。
第一个问题确实是由于
ensureVisible(sceneRect)
函数而发生的,该函数旨在确保给定的矩形在视图中可见。关于第二个问题,通过调用
qDebug() << viewportTransform()
,我发现m31
和m32
(转换组件)发生了变化,导致了偏移问题。要解决这个问题,我需要做的就是将m31和m32设置为0。这可以通过使用QGraphicsView::setSceneRect(0, 0, width, height)
来实现。