我有一个在屏幕中间有一个QGraphicsView
窗口的应用程序。我希望能够使用鼠标滚轮滚动来放大和缩小。
目前,我已经重新实现了QGraphicsView
并覆盖了鼠标滚动功能,这样它就不会滚动图像(就像它默认做的那样)。
void MyQGraphicsView::wheelEvent(QWheelEvent *event)
{
if(event->delta() > 0)
{
emit mouseWheelZoom(true);
}
else
{
emit mouseWheelZoom(false);
}
}
所以当我滚动时,如果鼠标滚轮向前,我会发出一个信号true,如果鼠标滚轮向后,我就会发出一个false信号。
然后,我将这个信号连接到处理GUI内容的类中的一个插槽(缩放函数,见下文)。现在基本上我认为我的缩放功能根本不是最好的方法,我见过一些人使用覆盖的车轮事件函数来设置比例的例子,但我真的找不到一个完整的答案。
因此,我已经这样做了,但无论如何它都不是完美的,所以我希望对它进行一些调整,或者寻找一个在轮子事件函数中使用scale的工作示例。
我在构造函数中将m_zoom_level
初始化为0
。
void Display::zoomfunction(bool zoom)
{
QMatrix matrix;
if(zoom && m_zoom_level < 500)
{
m_zoom_level = m_zoom_level + 10;
ui->graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
matrix.scale(m_zoom_level, m_zoom_level);
ui->graphicsView->setMatrix(matrix);
ui->graphicsView->scale(1,-1);
}
else if(!zoom)
{
m_zoom_level = m_zoom_level - 10;
ui->graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
matrix.scale(m_zoom_level, m_zoom_level);
ui->graphicsView->setMatrix(matrix);
ui->graphicsView->scale(1,-1);
}
}
正如你在上面看到的,我使用了一个QMatrix
和缩放,并将其设置为图形视图,并将变换锚点设置为在鼠标下,但它只是不能完美地工作,有时如果我滚动负载,它只会开始放大(我认为这与int循环或其他什么有关)。
正如我所说的,这方面的帮助或鼠标下的一个很好的缩放示例将是很好的。
发布于 2013-10-01 19:02:52
这样的缩放有点棘手。让我分享我自己的类来做这件事。
标题:
#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();
};
来源:
#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* z = new Graphics_view_zoom(ui->graphicsView);
z->set_modifiers(Qt::NoModifier);
发布于 2014-10-26 17:08:32
下面是一个使用PyQt的解决方案:
def wheelEvent(self, event):
"""
Zoom in or out of the view.
"""
zoomInFactor = 1.25
zoomOutFactor = 1 / zoomInFactor
# Save the scene pos
oldPos = self.mapToScene(event.pos())
# Zoom
if event.angleDelta().y() > 0:
zoomFactor = zoomInFactor
else:
zoomFactor = zoomOutFactor
self.scale(zoomFactor, zoomFactor)
# Get the new position
newPos = self.mapToScene(event.pos())
# Move scene to old position
delta = newPos - oldPos
self.translate(delta.x(), delta.y())
发布于 2015-03-13 15:29:39
这是适用于我的python版本。来自@Stefan Reinhardt和@rengel的答案的组合。
class MyQGraphicsView(QtGui.QGraphicsView):
def __init__ (self, parent=None):
super(MyQGraphicsView, self).__init__ (parent)
def wheelEvent(self, event):
# Zoom Factor
zoomInFactor = 1.25
zoomOutFactor = 1 / zoomInFactor
# Set Anchors
self.setTransformationAnchor(QtGui.QGraphicsView.NoAnchor)
self.setResizeAnchor(QtGui.QGraphicsView.NoAnchor)
# Save the scene pos
oldPos = self.mapToScene(event.pos())
# Zoom
if event.delta() > 0:
zoomFactor = zoomInFactor
else:
zoomFactor = zoomOutFactor
self.scale(zoomFactor, zoomFactor)
# Get the new position
newPos = self.mapToScene(event.pos())
# Move scene to old position
delta = newPos - oldPos
self.translate(delta.x(), delta.y())
https://stackoverflow.com/questions/19113532
复制相似问题