开发者

How to handle different situations in mouse event handler properly?

In my Qt application in the event handler for mouse press events I have such ugly code

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;
  }
}

Even without switching on mode_ variable the code looks terri开发者_Go百科ble. =( Two many degrees of freedom: button type, modifiers, ... Absolutely unreadable.

Is there any ways to overcome such a "heap of switches"?


One alternative approach is to use Qt's new State Machine Framework. I haven't used it myself, but from what I've read it's designed to replace your pile of state variables and switch statements with a simpler, more formal representation of the widget's behavior.


Observe that nested switches can be reversed: inner switches can be lifted to the outside and vice versa. This way, you can lift the switch on mode_ to the outer level.

A possible solution is then to create an interface, say Mode, that handles events for a particular mode:

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

Concrete implementations like ModeView and ModeEdit can then handle the events. If you do not want to handle all events in all cases, give this interface empty implementations instead of pure virtual functions. If there is shared functionality between particular modes, you can even create an intermediary class that those mode classes inherit from.

Let _mode be a pointer to a Mode to represent the current mode, and then your "master" handler becomes:

void Render::Viewer::mousePressEvent(QMouseEvent* e) {
  _mode->mousePressEvent(e);
}


It would be easier to read and maintain if you broke up tasks into their own functions:

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)
{
  ...
}

Break it up into however many functions you need to make it readable.


You could move some of your switch statements to functions

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜