在使用QGraphicsScene和QGraphicsView时,我想实现以下目标:如果鼠标位于屏幕的边界之一,则视图随之移动(就像大多数RTS游戏中的情况一样)。但是,当处理mouseMoveEvent时,我只会得到堆栈溢出,这很可能是因为一旦鼠标位于某个位置,该事件将被无限次调用。
我的相机类具有指向视图的指针,并继承QGraphicsRectItem并添加到主类的场景中。 有什么方法可以防止此事件在某个时刻发生?还是对此有一个优雅的解决方案?我尝试的另一个问题是,当我希望mouseMoveEvent工作时,相机类必须抓住鼠标。
void Camera::mouseMoveEvent(QGraphicsSceneMouseEvent* e)
{
int view_x = view->mapFromScene(e->pos()).x();
int view_y = view->mapFromScene(e->pos()).y();
int horizontalSliderPos = view->horizontalScrollBar()->sliderPosition();
int verticalSliderPos = view->verticalScrollBar()->sliderPosition();
if (view_x < 100) {
view->horizontalScrollBar()->setSliderPosition(horizontalSliderPos - 5);
}
if (view_x > Constants::VIEWWIDTH - 100) {
view->horizontalScrollBar()->setSliderPosition(view->horizontalScrollBar()->sliderPosition() + 5);
}
if (view_y < 100) {
view->verticalScrollBar()->setSliderPosition(view->verticalScrollBar()->sliderPosition() - 5);
}
if (view_y > Constants::VIEWHEIGHT - 100) {
view->verticalScrollBar()->setSliderPosition(view->verticalScrollBar()->sliderPosition() + 5);
}
}
答案 0 :(得分:0)
经过一些尝试和实验,我获得了一个解决方案,这可能是一个很好的起点。如前所述,您必须中断mouseMoveEvent
的递归调用。我用一个简单的布尔变量中断了递归调用,但是即使QSignalBlocker
也会阻止所有信号,但在这里还是有用的。
我尝试实现的另一个功能是,如果鼠标的空白处没有移动,则仍然有一个移动的窗口。我通过使用QTimer
(每25毫秒触发一次)来完成此操作。
main.cpp
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QMainWindow>
#include "MyScene.h"
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
auto view = new QGraphicsView;
auto model = new MyScene;
view->setMouseTracking(true);
view->setScene(model);
model->setView(view);
model->addRect(QRectF(20, 20, 20, 20));
model->addRect(QRectF(300, 20, 20, 20));
model->addRect(QRectF(0, 0, 500, 500), QPen(Qt::blue)); // Complete Scene
view->show();
view->setSceneRect(QRectF(120, 20, 20, 20));
return app.exec();
}
MyScene.h
#pragma once
#include <QDebug>
#include <QGraphicsSceneEvent>
#include <QGraphicsView>
#include <QTimer>
class MyScene : public QGraphicsScene {
Q_OBJECT
public:
MyScene(QWidget* parent=nullptr) : QGraphicsScene(parent) {
}
void setView(QGraphicsView* view) {
mView = view;
}
protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override {
if (mTranslating) return;
delete mRepeater; // Destroys connect
mRepeater = new QTimer;
if (!mView) return;
mTranslating = true;
int tx{ 0 };
int ty{ 0 };
const int margin = 20;
int sx = mView->mapFromGlobal(event->screenPos()).x();
int sy = mView->mapFromGlobal(event->screenPos()).y();
if (sx < margin) {
tx = -1;
}
else if (sx > mView->width() - margin) {
tx = 1;
}
if (sy < margin) {
ty = -1;
}
else if (sy > mView->height() - margin) {
ty = 1;
}
if (tx != 0 || ty != 0) {
auto rect = mView->sceneRect();
rect.translate(QPointF{ (qreal)tx,(qreal)ty });
mView->setSceneRect(rect);
connect(mRepeater, &QTimer::timeout, [=]() { // Moves even if mouse is not moved
auto rect = mView->sceneRect();
rect.translate(QPointF{ (qreal)tx,(qreal)ty });
mView->setSceneRect(rect);
});
mRepeater->start(25);
}
mTranslating = false;
}
QGraphicsView* mView{ nullptr };
bool mTranslating{ false };
QTimer* mRepeater{ nullptr };
};
答案 1 :(得分:0)
我认为,如果您在QGraphicsView类中处理鼠标移动事件而不是在QGraphicsScene类中处理鼠标移动事件,则可以避免。