问题描述
我有简单的 cpp 代码。我想用鼠标移动 QGraphicsScene:
// MainWindow.cpp code ------------------------------
void MainWindow::initializeMainViewWidget() {
/* some code */
itemsFrame->setLayout(layout);
mView = std::make_unique<ui::MainView>();
layout->addWidget(mView.get());
mScene = std::make_unique<ui::MainScene>();
mView->setScene(mScene.get());
QObject::connect(mScene.get(),&ui::MainScene::openItem,this,&MainWindow::openUpdateItemDialog);
mView->show();
}
// MainView.cpp code -------------------------------
void MainView::mousepressEvent(QMouseEvent *event) {
if (event->button() == Qt::RightButton) {
// Store original position.
mPos0 = event->position(); //mPos0 is QPointF
event->accept();
setCursor(Qt::ClosedHandCursor);
return;
} else if (event->button() == Qt::LeftButton) {
event->ignore();
}
QGraphicsView::mousepressEvent(event);
}
void MainView::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
event->ignore();
} else if (event->buttons() & Qt::RightButton) {
QPointF trans = event->position() - mPos0;
mPos0 = event->position();
event->accept();
translate(trans.x(),trans.y());
return;
}
QGraphicsView::mouseMoveEvent(event);
}
但是当我通过以下方式添加项目时: addItem(someQGraphicsItem);
显示项目。我可以拖动它......但不能用RMB和mouseMove移动场景。
解决方法
我从 SO: Zoom functionality using Qt 中获取了我的旧样本,并添加了通过鼠标拖动来平移内容的代码:
#include <QtWidgets>
// class for widget to demonstrate zooming
class Canvas: public QGraphicsView {
// variables:
private:
// start position for pan
QPoint _posRMB;
// methods:
public:
// constructor.
Canvas() = default;
// destructor.
virtual ~Canvas() = default;
// disabled:
Canvas(const Canvas&) = delete;
Canvas& operator=(const Canvas&) = delete;
protected:
virtual void mousePressEvent(QMouseEvent *pQEvent) override
{
if (pQEvent->button() == Qt::RightButton) {
_posRMB = pQEvent->pos();
pQEvent->accept();
setCursor(Qt::ClosedHandCursor);
}
}
virtual void mouseMoveEvent(QMouseEvent *pQEvent) override
{
if (pQEvent->buttons() & Qt::RightButton) {
// pos() -> virtual canvas,_posRMB -> virtual canvas
QPointF delta = mapToScene(pQEvent->pos()) - mapToScene(_posRMB);
// modify transform matrix
translate(delta.x(),delta.y());
_posRMB = pQEvent->pos();
// force update
update();
pQEvent->accept();
}
}
virtual void mouseReleaseEvent(QMouseEvent *pQEvent)
{
if (pQEvent->button() == Qt::RightButton) {
unsetCursor();
}
}
virtual void wheelEvent(QWheelEvent *pQEvent) override
{
//qDebug() << "Wheel Event:";
// pos() -> virtual canvas
QPointF pos = mapToScene(pQEvent->pos());
// scale from wheel angle
float delta = 1.0f + pQEvent->angleDelta().y() / 1200.0f;
// modify transform matrix
QTransform xform = transform();
xform.translate(pos.x(),pos.y()); // origin to spot
xform.scale(delta,delta); // scale
xform.translate(-pos.x(),-pos.y()); // spot to origin
setTransform(xform);
// force update
update();
pQEvent->accept();
}
};
QRectF toScr(QWidget *pQWidget,float x,float y,float w,float h)
{
const int wView = pQWidget->width(),hView = pQWidget->height();
const int s = wView < hView ? wView : hView;
return QRectF(
(0.5f * x + 0.5f) * s,(0.5f * y + 0.5f) * s,0.5f * w * s,0.5f * h * s);
}
int main(int argc,char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc,argv);
// setup GUI
Canvas canvas;
canvas.setTransformationAnchor(QGraphicsView::NoAnchor);
canvas.setDragMode(QGraphicsView::NoDrag);
canvas.resize(256,256);
canvas.show();
// prepare scene
QGraphicsScene qGScene;
qGScene.addRect(toScr(canvas.viewport(),-1.0f,2.0f,2.0f),QColor(0x000000u));
qGScene.addRect(toScr(canvas.viewport(),-0.2f,0.4f,0.4f),QColor(0x00ff00u));
qGScene.addRect(toScr(canvas.viewport(),-0.8f,QColor(0xff0000u));
qGScene.addRect(toScr(canvas.viewport(),QColor(0x0000ffu));
qGScene.addRect(toScr(canvas.viewport(),QColor(0xff00ffu));
qGScene.addRect(toScr(canvas.viewport(),QColor(0xffff00u));
canvas.setScene(&qGScene);
// runtime loop
return app.exec();
}
输出:
我挣扎了一段时间才让它按预期运行,直到我意识到
QPointF delta = mapToScene(pQEvent->pos() - _posRMB); // Not working!
不一样
QPointF delta = mapToScene(pQEvent->pos()) - mapToScene(_posRMB);
此外,禁用 QGraphicsView
的自动适应视图很重要:
canvas.setTransformationAnchor(QGraphicsView::NoAnchor);
在再次思考 OP 问题时,我意识到另一个可能的问题:
如果场景小于视图,它会自动对齐。 (涉及到 QGraphicsView::alignment。)
在我的演示会话中,我从放大开始,以防止出现此问题。
另一种选择,即使场景比视图小,也可以拖动场景 - 可以通过显式设置 QGraphicsView::sceneRect 来调整场景大小。
在滚动文档时。 QGrapicsView 我注意到:
拖动模式:DragMode
该属性保存在按下鼠标左键时在场景上拖动鼠标的行为。
这个属性定义了当用户点击场景背景并拖动鼠标(例如,使用指向手形光标滚动视口内容,或使用橡皮筋选择多个项目)时应该发生的情况。默认值 NoDrag 什么也不做。
此行为仅影响未由任何项目处理的鼠标点击。您可以通过创建 QGraphicsView 的子类并重新实现 mouseMoveEvent() 来定义自定义行为。
我觉得值得一提。