Как правильно обрабатывать различные ситуации в обработчике мыши? - PullRequest
1 голос
/ 12 ноября 2009

В моем приложении 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;
  }
}

Даже без включения переменной mode_ код выглядит ужасно. = (Две много степеней свободы: тип кнопки, модификаторы, ... Абсолютно не читается.

Есть ли способы преодоления такой "кучи переключателей"?

Ответы [ 4 ]

4 голосов
/ 12 ноября 2009

Один из альтернативных подходов - использовать новую State Machine Framework Qt . Я не использовал его сам, но из того, что я прочитал, он предназначен для замены вашей кучи переменных состояния и операторов переключения на более простое, более формальное представление поведения виджета.

4 голосов
/ 12 ноября 2009

Обратите внимание, что вложенные переключатели можно перевернуть: внутренние переключатели можно поднять наружу и наоборот. Таким образом, вы можете поднять переключатель на mode_ до внешнего уровня.

Возможное решение - создать интерфейс, скажем Mode, который обрабатывает события для определенного режима:

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

Конкретные реализации, такие как ModeView и ModeEdit, могут затем обрабатывать события. Если вы не хотите обрабатывать все события во всех случаях, предоставьте этому интерфейсу пустые реализации вместо чисто виртуальных функций. Если между отдельными режимами есть общие функции, вы даже можете создать промежуточный класс, от которого наследуются эти классы режимов.

Пусть _mode будет указателем на Mode для представления текущего режима, и тогда ваш «главный» обработчик станет:

void Render::Viewer::mousePressEvent(QMouseEvent* e) {
  _mode->mousePressEvent(e);
}
2 голосов
/ 12 ноября 2009

Было бы легче читать и поддерживать, если бы вы разбили задачи на их собственные функции:

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

Разбейте его на столько функций, сколько нужно, чтобы сделать его читабельным.

1 голос
/ 12 ноября 2009

Вы можете переместить некоторые из своих операторов switch в функции

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...