C++ QGraphicsView当图像小于视图时将图像缩放到光标
我正在尝试实现一个代码,它可以放大图像并将图像移向光标,但不能完全重新定位光标的中心(类似于谷歌地图的工作方式,或者完全类似于Picasa Photo Viewer过去的工作方式,如果有人看到的话)。关键是,它需要放大图像,并使鼠标光标下的像素保持不变 的可接受答案中提供的示例代码很接近,但并不能完全解决问题,因为这是moreso的问题,因此如何使用光标放大并避开QGraphicsView中固有的问题 问题是:正如示例代码标题中的注释所示,如果视图大于图像,则无法执行此功能。换句话说,如果您缩小图像,使其没有滚动条,然后放大,图像将放大到中心,而不是鼠标光标;只有放大到有水平和垂直滚动条的程度,它才能放大到光标,并在光标下保持相同的像素 这似乎是QGraphicsView的一个基本问题:QGraphicsView::setTransformationAnchor(QGraphicsView::AnchorUnderMouse)可以获得几乎完全相同的结果,但Qt文档报告了相同的问题: 请注意,当只有场景的一部分可见时(即,当存在滚动条时),此属性的效果是明显的。否则,如果整个场景适合视图,QGraphicscene将使用视图对齐在视图中定位场景 我怀疑这是因为这两种方法都在滚动视口,但如果图像与视口相比太小,则无法实际滚动图像 我怀疑解决方案可能需要放弃滚动并实际移动图像,但我不知道如何移动图像,使相同的像素停留在鼠标光标下 以下是一些我已经实现但不起作用的代码: 图形\视图\缩放。h:C++ QGraphicsView当图像小于视图时将图像缩放到光标,c++,image,qt,scroll,qgraphicsview,C++,Image,Qt,Scroll,Qgraphicsview,我正在尝试实现一个代码,它可以放大图像并将图像移向光标,但不能完全重新定位光标的中心(类似于谷歌地图的工作方式,或者完全类似于Picasa Photo Viewer过去的工作方式,如果有人看到的话)。关键是,它需要放大图像,并使鼠标光标下的像素保持不变 的可接受答案中提供的示例代码很接近,但并不能完全解决问题,因为这是moreso的问题,因此如何使用光标放大并避开QGraphicsView中固有的问题 问题是:正如示例代码标题中的注释所示,如果视图大于图像,则无法执行此功能。换句话说,如果您缩小
#include <QObject>
#include <QGraphicsView>
/*!
* This class adds ability to zoom QGraphicsView using mouse wheel. The point under cursor
* remains motionless while it's possible.
*
* Note that it becomes not possible when the scene's
* size is not large enough comparing to the viewport size. QGraphicsView centers the picture
* when it's smaller than the view. And QGraphicsView's scrolls boundaries don't allow to
* put any picture point at any viewport position.
*
* When the user starts scrolling, this class remembers original scene position and
* keeps it until scrolling is completed. It's better than getting original scene position at
* each scrolling step because that approach leads to position errors due to before-mentioned
* positioning restrictions.
*
* When zommed using scroll, this class emits zoomed() signal.
*
* Usage:
*
* new Graphics_view_zoom(view);
*
* The object will be deleted automatically when the view is deleted.
*
* You can set keyboard modifiers used for zooming using set_modified(). Zooming will be
* performed only on exact match of modifiers combination. The default modifier is Ctrl.
*
* You can change zoom velocity by calling set_zoom_factor_base().
* Zoom coefficient is calculated as zoom_factor_base^angle_delta
* (see QWheelEvent::angleDelta).
* The default zoom factor base is 1.0015.
*/
class Graphics_view_zoom : public QObject {
Q_OBJECT
public:
Graphics_view_zoom(QGraphicsView* view);
void gentle_zoom(double factor);
void set_modifiers(Qt::KeyboardModifiers modifiers);
void set_zoom_factor_base(double value);
private:
QGraphicsView* _view;
Qt::KeyboardModifiers _modifiers;
double _zoom_factor_base;
QPointF target_scene_pos, target_viewport_pos;
bool eventFilter(QObject* object, QEvent* event);
signals:
void zoomed();
};
#包括
#包括
/*!
*此类增加了使用鼠标滚轮缩放QGraphicsView的功能。光标下的点
*尽可能保持静止。
*
*请注意,当场景的
*与视口大小相比,大小不够大。QGraphicsView使图片居中
*当它小于视图时。QGraphicsView的卷轴边界不允许
*在任何视口位置放置任何图片点。
*
*当用户开始滚动时,此类会记住原始场景位置和
*保留它直到滚动完成。这比在一个位置获取原始场景位置要好
*由于上述原因,每个滚动步骤都会导致位置错误
*定位限制。
*
*当使用scroll进行僵尸化时,此类会发出Zomed()信号。
*
*用法:
*
*新图形\视图\缩放(视图);
*
*删除视图时,对象将自动删除。
*
*可以使用set_modified()设置用于缩放的键盘修改器。变焦将是一个巨大的挑战
*仅在修改器组合完全匹配的情况下执行。默认的修改器是Ctrl。
*
*可以通过调用set_zoom_factor_base()更改缩放速度。
*缩放系数计算为缩放系数^基准^角度^增量
*(请参见QWheelEvent::angleDelta)。
*默认的缩放因子基数为1.0015。
*/
类图形\视图\缩放:公共QObject{
Q_对象
公众:
图形视图缩放(QGraphicsView*视图);
void和u缩放(双因子);
void set_修饰符(Qt::keyboard修饰符修饰符);
无效集\缩放\系数\基准(双倍值);
私人:
QGraphicsView*\u视图;
Qt::键盘修饰符_修饰符;
双缩放因子基数;
QPointF目标\场景\位置、目标\视口\位置;
bool事件过滤器(QObject*对象,QEvent*事件);
信号:
void缩放();
};
图形\视图\缩放.cpp:
#include "Graphics_view_zoom.h"
#include <QMouseEvent>
#include <QApplication>
#include <QScrollBar>
#include <qmath.h>
Graphics_view_zoom::Graphics_view_zoom(QGraphicsView* view)
: QObject(view), _view(view)
{
_view->viewport()->installEventFilter(this);
_view->setMouseTracking(true);
_modifiers = Qt::ControlModifier;
_zoom_factor_base = 1.0015;
}
void Graphics_view_zoom::gentle_zoom(double factor) {
_view->scale(factor, factor);
_view->centerOn(target_scene_pos);
QPointF delta_viewport_pos = target_viewport_pos - QPointF(_view->viewport()->width() / 2.0,
_view->viewport()->height() / 2.0);
QPointF viewport_center = _view->mapFromScene(target_scene_pos) - delta_viewport_pos;
_view->centerOn(_view->mapToScene(viewport_center.toPoint()));
emit zoomed();
}
void Graphics_view_zoom::set_modifiers(Qt::KeyboardModifiers modifiers) {
_modifiers = modifiers;
}
void Graphics_view_zoom::set_zoom_factor_base(double value) {
_zoom_factor_base = value;
}
bool Graphics_view_zoom::eventFilter(QObject *object, QEvent *event) {
if (event->type() == QEvent::MouseMove) {
QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
QPointF delta = target_viewport_pos - mouse_event->pos();
if (qAbs(delta.x()) > 5 || qAbs(delta.y()) > 5) {
target_viewport_pos = mouse_event->pos();
target_scene_pos = _view->mapToScene(mouse_event->pos());
}
} else if (event->type() == QEvent::Wheel) {
QWheelEvent* wheel_event = static_cast<QWheelEvent*>(event);
if (QApplication::keyboardModifiers() == _modifiers) {
if (wheel_event->orientation() == Qt::Vertical) {
double angle = wheel_event->angleDelta().y();
double factor = qPow(_zoom_factor_base, angle);
gentle_zoom(factor);
return true;
}
}
}
Q_UNUSED(object)
return false;
}
#包括“Graphics_view_zoom.h”
#包括
#包括
#包括
#包括
图形视图缩放::图形视图缩放(QGraphicsView*视图)
:QObject(视图),\u视图(视图)
{
_视图->视口()->installEventFilter(此);
_查看->设置鼠标追踪(真);
_修饰符=Qt::ControlModifier;
_缩放系数\基数=1.0015;
}
无效图形\视图\缩放::柔和\缩放(双因素){
_查看->比例(因子,因子);
_查看->中心(目标\场景\位置);
QPointF delta_viewport_pos=目标_viewport_pos-QPointF(_view->viewport()->width()/2.0,
_视图->视口()->高度()/2.0);
QPointF viewport\u center=\u view->mapFromScene(target\u scene\u pos)-delta\u viewport\u pos;
_视图->中心点(_视图->地图场景(viewport_center.toPoint());
发射缩放();
}
无效图形\视图\缩放::设置\修改器(Qt::键盘修改器){
_修饰符=修饰符;
}
无效图形\视图\缩放::设置\缩放\系数\基础(双值){
_缩放系数\基准=值;
}
bool Graphics\u view\u zoom::eventFilter(QObject*object,QEvent*event){
如果(事件->类型()==QEvent::MouseMove){
QMouseEvent*鼠标事件=静态播放(事件);
QPointF delta=target_viewport_pos-鼠标事件->pos();
if(qab(delta.x())>5 | | qab(delta.y())>5){
目标\视口\位置=鼠标\事件->位置();
目标\场景\位置=\视图->映射场景(鼠标\事件->位置());
}
}else if(事件->类型()==QEvent::Wheel){
QWheelEvent*wheel_事件=静态_投射(事件);
如果(QApplication::keyboardModifiers()==\u修饰符){
如果(车轮事件->方向()==Qt::垂直){
双角度=车轮事件->角度增量();
双因子=qPow(缩放因子、基准、角度);
平缓变焦(系数);
返回true;
}
}
}
Q_未使用(对象)
返回false;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#包括“mainwindow.h”
#包括
int main(int argc,char*argv[])
{
质量保证申请a(argc、argv);
主窗口w;
w、 show();
返回a.exec();
}
主风
#pragma once
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
};
#include "mainwindow.h"
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QPixmap>
#include <Graphics_view_zoom.h>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
this->setFixedSize(1000,1000);
QGraphicsScene* s = new QGraphicsScene(this);
QGraphicsView* v = new QGraphicsView(this);
Graphics_view_zoom* z = new Graphics_view_zoom(v);
z->set_modifiers(Qt::NoModifier);
v->setScene(s);
v->setFixedSize(1000,1000);
QPixmap pix;
if(pix.load("C:\\full\\path\\to_an_image_file.jpg"))
{
s->addPixmap(pix);
}
}