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
精彩评论