【问题标题】:QWheelEvent not working when using N.2 QGraphicsView in the same UI在同一 UI 中使用 N.2 QGraphicsView 时 QWheelEvent 不起作用
【发布时间】:2019-05-17 08:25:41
【问题描述】:

我正在构建一个具有 N.2 QGraphicsView 的用户界面,我正在 只能放大一个 QGraphicsView。 我将 QWheelEvent + CTRL 用于一个 QGraphicsView 和 QWheelEvent + ALT 用于第二个 QGraphicsView。

我阅读了非常有用的文章来开发此程序,例如 thisthis 但所有这些都是为了放大一个 QGraphicsView。所以 很抱歉再次写这个问题,但我一直在努力 过去几天很多,因为我试图为两个不同的 QGraphicsView..

我包含了代码的 sn-p(主要是我使用来自 this post 的代码 ) 进行缩放。请让我知道我做错了什么。

ma​​inwindow.h

private:
    Qt::KeyboardModifiers _modifiers;
    double _zoom_factor_base;
    QPointF target_scene_pos, target_viewport_pos;
    bool eventFilter(QObject* object, QEvent* event);

    Qt::KeyboardModifiers _modifiersRight;
    double _zoom_factor_base_right;
    QPointF target_scene_pos_right, target_viewport_pos_right;
    bool altDown = false;

signals:
    void zoomed();
    void zoomedRight();

protected:
    void keyPressEvent(QKeyEvent *event);
    void keyReleaseEvent(QKeyEvent *event);

ma​​inwindow.cpp

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{    
     ui->setupUi(this);
     ui->leftView->viewport()->installEventFilter(this);
     ui->leftView->setMouseTracking(true);
     _modifiers = Qt::ControlModifier;
     _zoom_factor_base = 1.0015;
     ui->rightView->viewport()->installEventFilter(this);
     ui->rightView->setMouseTracking(true);
     _modifiersRight = Qt::ControlModifier;
     _zoom_factor_base_right = 1.0015;
}

void MainWindow::gentle_zoom(double factor)
{
     ui->leftView->scale(factor, factor);
     ui->leftView->centerOn(target_scene_pos);
     QPointF delta_viewport_pos = target_viewport_pos - QPointF(ui->leftView->viewport()->width() / 2.0,

     ui->leftView->viewport()->height() / 2.0);
     QPointF viewport_center =
     ui->leftView->mapFromScene(target_scene_pos) - delta_viewport_pos;
     ui->leftView->centerOn(ui->leftView >mapToScene(viewport_center.toPoint()));
     emit zoomed();
}
void MainWindow::set_modifiers(Qt::KeyboardModifiers modifiers)
{
     _modifiers = modifiers;
}

void MainWindow::set_zoom_factor_base(double value)
{
     _zoom_factor_base = value;
}

void MainWindow::gentle_zoom_right(double factor)
{
     ui->rightView->scale(factor, factor);
     ui->rightView->centerOn(target_scene_pos_right);
     QPointF delta_viewport_pos = target_viewport_pos_right -
     QPointF(ui->rightView->viewport()->width() / 2.0,

     ui->rightView->viewport()->height() / 2.0);
     QPointF viewport_center = ui->rightView->mapFromScene(target_scene_pos_right) - delta_viewport_pos;
     ui->rightView->centerOn(ui->rightView >mapToScene(viewport_center.toPoint())); 
     emit zoomedRight();
 }

void MainWindow::set_modifiers_right(Qt::KeyboardModifiers modifiers)
{
     _modifiersRight = modifiers;
}

void MainWindow::set_zoom_factor_base_right(double value)
{
     _zoom_factor_base_right = value;
}

bool MainWindow::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 = ui->leftView->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_right, angle);
                      gentle_zoom(factor);
                      return true;
                  }
              }
         }
         if(altDown) // I repeat the same procedure but for the rightView
         {
              if (event->type() == QEvent::MouseMove)
              {
                   QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
                   QPointF delta = target_viewport_pos_right - mouse_event->pos();
                   if (qAbs(delta.x()) > 5 || qAbs(delta.y()) > 5)
                   {
                        target_viewport_pos_right = mouse_event->pos();
                        target_scene_pos_right = ui->rightView->mapToScene(mouse_event->pos());
                    }
                }
                else if (event->type() == QEvent::Wheel)
                {
                    QWheelEvent* wheel_event = static_cast<QWheelEvent*>(event);
                    if (QApplication::keyboardModifiers() == _modifiersRight)
                    {
                         if (wheel_event->orientation() == Qt::Vertical)
                         {
                             double angle = wheel_event->angleDelta().y();
                             double factor = qPow(_zoom_factor_base_right, angle);
                             gentle_zoom_right(factor);
                             return true;
                         }
                    }
                }
          }
          Q_UNUSED(object)
          return false;
}

void MainWindow::keyReleaseEvent(QKeyEvent *event)
{
     if(event->key() == Qt::Key_Alt) { altDown = false; }
}

void MainWindow::keyPressEvent(QKeyEvent *event)
{
     if(event->key() == Qt::Key_Alt) { altDown = true; }
}

【问题讨论】:

    标签: c++ qt qt5 qgraphicsview


    【解决方案1】:

    你必须了解Single responsibility principle,它表明每个班级都有自己的责任,在这种情况下,它会避免很多混乱。缩放的责任是 QGraphicsView,它不是 MainWindow 的责任。

    为此,创建了一个继承自 QGraphicsView 的新类,我们实现了缩放功能:

    graphicsview.h

    #ifndef GRAPHICSVIEW_H
    #define GRAPHICSVIEW_H
    
    #include <QGraphicsView>
    
    class GraphicsView : public QGraphicsView
    {
    public:
        GraphicsView(QWidget *parent=nullptr);
        void setModifiers(const Qt::KeyboardModifiers &modifiers);
    protected:
        void wheelEvent(QWheelEvent *event) override;
    private:
        void applyZoom(double factor, const QPoint &fixedViewPos);
        Qt::KeyboardModifiers m_modifiers;
        const double base = 1.0015;
    };
    
    #endif // GRAPHICSVIEW_H
    

    graphicsview.cpp

    #include "graphicsview.h"
    
    #include <QWheelEvent>
    #include <QtMath>
    
    GraphicsView::GraphicsView(QWidget *parent):
        QGraphicsView(parent)
    {}
    
    void GraphicsView::setModifiers(const Qt::KeyboardModifiers &modifiers)
    {
        m_modifiers = modifiers;
    }
    
    void GraphicsView::wheelEvent(QWheelEvent *event)
    {
        if(event->modifiers() == m_modifiers){
            double angle = event->orientation() == Qt::Vertical ? event->angleDelta().y(): event->angleDelta().x();
            double factor = qPow(base, angle);
            applyZoom(factor, event->pos());
        }
    }
    
    void GraphicsView::applyZoom(double factor, const QPoint & fixedViewPos)
    {
        QPointF fixedScenePos = mapToScene(fixedViewPos);
        centerOn(fixedScenePos);
        scale(factor, factor);
        QPointF delta = mapToScene(fixedViewPos) - mapToScene(viewport()->rect().center());
        centerOn(fixedScenePos - delta);
    }
    

    然后使用 Qt Designer 提供的小部件promotion 将其插入 GUI。然后设置值:

    ui->rightView->setModifiers(Qt::AltModifier);
    ui->leftView->setModifiers(Qt::ControlModifier);
    

    完整的例子可以在here找到。


    另一方面,SO 中显示的许多代码示例只是为了展示功能,不一定用于项目的实施,因为这里的空间很小,有时会被压缩,失去可读性。例如,我基于您指出的答案的想法,但我已将其正确划分以获得干净的代码。

    【讨论】:

    • 非常感谢 eyllanesc 提供的示例代码。它非常有用,我可以继续我的项目。还要感谢您的彻底解释,使概念真正清晰。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-01
    • 1970-01-01
    • 2015-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多