2009-11-12 4 views
1

Dans mon application Qt dans le gestionnaire d'événements pour les événements de presse de souris J'ai un tel code laidComment gérer correctement différentes situations dans le gestionnaire d'événements de la souris?

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

Même sans allumer la variable MODE_ le code semble terrible. = (Deux nombreux degrés de liberté:.? type bouton, modificateurs, ... Absolument illisible

Y at-il des moyens de surmonter un tel « tas de commutateurs »

Répondre

2

Il serait plus facile à lire et à maintenir si vous avez rompu les tâches dans leurs propres fonctions.

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 en revanche de nombreuses fonctions dont vous avez besoin pour le rendre lisible

+0

Merci, Bill . La réponse est évidente. =) "Diviser et conquérir". Comment pourrais-je oublier ce principe ?! – Wildcat

4

Une approche alternative consiste à utiliser les nouvelles State Machine Framework de Qt, je ne l'ai pas utilisé. moi-même, mais de ce que je Il est conçu pour remplacer votre pile de variables d'état et changer les instructions avec une représentation plus simple et plus formelle du comportement du widget.

+0

Neat, merci pour le lien! – Bill

4

Observez que les commutateurs imbriqués peuvent être inversés: les commutateurs internes peuvent être levés vers l'extérieur et inversement. De cette façon, vous pouvez soulever l'interrupteur mode_ au niveau externe.

Une solution possible est alors de créer une interface, par exemple Mode, qui gère les événements pour un mode particulier:

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

implémentations concrètes comme ModeView et ModeEdit peuvent alors gérer les événements. Si vous ne voulez pas gérer tous les événements dans tous les cas, donnez à cette interface des implémentations vides au lieu de fonctions virtuelles pures. S'il existe des fonctionnalités partagées entre des modes particuliers, vous pouvez même créer une classe intermédiaire héritée de ces classes de mode.

Soit _mode être un pointeur vers un Mode pour représenter le mode actuel, puis votre gestionnaire « maître » devient:

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

Merci, Thomas. Si je comprends bien, c'est un modèle de conception d'état. N'est-ce pas? – Wildcat

+0

Pourrait être. \ * googles ... \ * Oui, c'est vrai. – Thomas

1

Vous pouvez déplacer certaines de vos déclarations de commutation aux fonctions

Questions connexes