代码之家  ›  专栏  ›  技术社区  ›  Wildcat

如何正确处理鼠标事件处理程序中的不同情况?

  •  1
  • Wildcat  · 技术社区  · 15 年前

    在我的qt应用程序中,在鼠标按下事件的事件处理程序中,我有这么难看的代码

    void Render::Viewer::mousePressEvent(QMouseEvent* e)
    {
      switch (e->button())
      {
      case Qt::LeftButton:
        switch (mode_)
        {
        case Render::Viewer::ModeView:
          switch (e->modifiers())
          {
          case Qt::NoModifier:
            ...
            break;
          ...
          default:
            break;
          }
          break;
        case Render::Viewer::ModeEdit:
          ...
          break;
        }
        break;
      case Qt::RightButton:
        ...
        break;
      }
    }
    

    即使没有打开模式变量,代码看起来也很糟糕。=(两个自由度:按钮类型、修改器,…绝对不可读。

    有没有什么方法可以克服这种“开关堆”?

    4 回复  |  直到 15 年前
        1
  •  2
  •   Bill    15 年前

    如果您将任务分解为它们自己的功能,则更容易阅读和维护:

    void Render::Viewer::mousePressEvent(QMouseEvent* e) 
    { 
      switch (e->button()) 
      { 
      case Qt::LeftButton: 
        handleLeftButton(e);
        break;
      case Qt::RightButton: 
        handleRightButton(e);
        break; 
      } 
    }
    
    void Render::Viewer::handleLeftButton(QMouseEvent* e)
    {
        switch (mode_) 
        { 
        case Render::Viewer::ModeView: 
          switch (e->modifiers()) 
          { 
          case Qt::NoModifier: 
            ... 
            break; 
          ... 
          default: 
            break; 
          } 
          break; 
        case Render::Viewer::ModeEdit: 
          ... 
          break; 
        } 
    }
    
    void Render::Viewer::handleRightButton(QMouseEvent* e)
    {
      ...
    }
    

    将它分解成您需要的许多函数,以使其可读。

        2
  •  4
  •   Jeremy Friesner    15 年前

    另一种方法是使用qt的 State Machine Framework .我自己没有使用它,但是从我读到的内容来看,它被设计成用一个更简单、更正式的小部件行为表示来替换您的一堆状态变量和switch语句。

        3
  •  4
  •   Thomas    15 年前

    注意嵌套开关可以反转:内部开关可以提升到外部,反之亦然。这样,你可以打开开关 mode_ 到外层。

    一个可能的解决方案是创建一个接口,比如 Mode ,处理特定模式的事件:

    class Mode {
      public:
        virtual void mousePressEvent(QMouseEvent *e) = 0;
        // ... and so on for other events
    };
    

    具体实现如 ModeView ModeEdit 然后可以处理事件。如果您不想在所有情况下处理所有事件,请将此接口的实现为空,而不是纯虚拟函数。如果特定模式之间存在共享功能,则甚至可以创建那些模式类继承自的中间类。

    _mode 作为指向 模式 要表示当前模式,然后您的“主”处理程序变为:

    void Render::Viewer::mousePressEvent(QMouseEvent* e) {
      _mode->mousePressEvent(e);
    }
    
        4
  •  1
  •   Nick    15 年前

    您可以将一些switch语句移动到函数