2017-09-16 5 views
0

Je suis en train de coder des widgets personnalisés en FLTK, l'un est un spinner à un chiffre pour un écran tactile qui est une valeur avec une flèche au-dessus et une autre ci-dessous.Le rappel Fl_Button n'est pas appelé

class Spinner: public Fl_Group 
{ 
private: 
    ::std::unique_ptr<Fl_Button> button_up_; 
    ::std::unique_ptr<Fl_Button> button_down_; 
    ::std::unique_ptr<Fl_Output> value_; 
public: 
    static unsigned int const WIDTH = 36; 
    static unsigned int const HEIGHT = 100; 
... 
}; 

Spinner::Spinner(int x, int y, size_t val) 
     :Fl_Group(x, y, WIDTH, HEIGHT) 
     ,button_up_(new Fl_Button(x + 2, y + 1, 32, 17)) 
     ,button_down_(new Fl_Button(x + 2, y + 82, 32, 17)) 
     ,value_(new Fl_Output(x + 2, y + 18, 32, 64)) 
{ 
    char v[] = {'0', 0}; 
    if (val > 9) val = 9; 
    v[0] = val + '0'; 
    button_up_->callback(reinterpret_cast<Fl_Callback*>(&Spinner::upcbk), this); 
    button_down_->callback(reinterpret_cast<Fl_Callback*>(&Spinner::downcbk), this); 
    button_up_->image(up_arrow); 
    button_down_->image(down_arrow); 
    button_up_->color(FL_BLACK); 
    button_down_->color(FL_BLACK); 
    button_up_->box(FL_FLAT_BOX); 
    button_down_->box(FL_FLAT_BOX); 
    value_->box(FL_BORDER_BOX); 
    value_->color(FL_BLACK); 
    value_->labelcolor(FL_RED); 
    value_->selection_color (FL_RED); 
    value_->textsize(46); 
    value_->textcolor(FL_RED); 
    value_->value(v); 
    value_->redraw(); 
    end(); 
} 

void Spinner::upcbk(Fl_Widget*, Spinner* spnr) 
{ 
    cout << "Spinner::upcbk()" << endl; 
    spnr->increment(); 
} 

void Spinner::downcbk(Fl_Widget*, Spinner* spnr) 
{ 
    cout << "Spinner::downcbk()" << endl; 
    spnr->decrement(); 
} 

Quand j'instancier un objet Spinner dans la fenêtre, il fonctionne bien et chaque rappel est appelée lorsque l'utilisateur clique sur sa flèche correspondante.

L'autre widget personnalisé est un agregation Spinner:

class UintSpinner: public Fl_Group 
{ 
private: 
    uint16_t value_; 
    uint16_t const max_; 
    uint16_t const min_; 
    uint16_t const order_; 
    char fmt_[6]; 
    ::std::vector< ::std::unique_ptr <Spinner> > spinners_; 
... 
}; 

UintSpinner::UintSpinner(int x, int y, uint16_t minval, uint16_t maxval 
         ,uint16_t val) 
     :Fl_Group(x, y, Spinner::WIDTH * static_cast<uint16_t>(log10(max_)) + 1, Spinner::HEIGHT) 
     ,value_(val < minval ? minval : (val > maxval ? maxval : val)) 
     ,max_(maxval) 
     ,min_(minval) 
     ,order_(static_cast<uint16_t>(log10(max_)) + 1) 
{ 
    strncpy(fmt_, "%00hu", 6); 
    fmt_[2] = static_cast<char>(order_) + '0'; 
    char buffer[6]; 
    snprintf(buffer, 6, fmt_, val); 
    for (ssize_t i = order_ - 1; i >= 0; i--) { 
     spinners_.emplace_back(new Spinner(x + i * Spinner::WIDTH, y, buffer[i] - '0')); 
     spinners_.back()->callback(&UintSpinner::spinner_cb, this); 
    } 
} 

void UintSpinner::spinner_cb(Fl_Widget* cb, void* p) 
{ 
    cout << "UintSpinner::spinner_cb()" << endl; 
    reinterpret_cast<UintSpinner*>(p)->spinnercb(); 
} 

Dans ce cas, si j'istantiate un objet de classe UintSpinner avec une valeur maximale de 244, il rend correctement trois fileuses individuels mais ni Spinner :: upcbk ni Spinner :: downcbk s'appelle quand je frappe une des flèches.

J'ai essayé d'utiliser des variables de pile pour Fl_Button et Fl_Output dans la classe Spinner et le comportement est le même. J'ai aussi essayé de créer un vecteur de Spinners au lieu d'un vecteur de pointeurs mais il ne compile pas car le Fl_Group ne semble pas mobile.

Est-ce que je fais quelque chose de mal? Pourquoi utiliser exactement le même code dans la classe Spinner, les callbacks internes des membres fonctionnent-ils lorsque vous utilisez cette instance directement et non lorsque vous utilisez l'instance dans un autre widget personnalisé?

Meilleures salutations et merci de votre aide.

Répondre

0

Ok, j'ai trouvé la solution.

Dans le constructeur UintSpinner, lorsque j'appelle le constructeur de base Fl_Group, je transmets un paramètre de largeur avec une valeur indéfinie (une erreur de copier-coller). Selon Erco's FLTK Cheat Page -> Fl_Group Event vs. Draw Clipping lorsque les enfants d'un Fl_Group se développent en dehors de sa zone de délimitation, par défaut le rendu n'est pas écrêté mais ses événements de souris sont. Donc changer le constructeur à:

UintSpinner::UintSpinner(int x, int y, uint16_t minval, uint16_t maxval 
         ,uint16_t val) 
     :Fl_Group(x, y, Spinner::WIDTH * static_cast<uint16_t>(log10(maxval) + 1), Spinner::HEIGHT) 
     ,value_(val < minval ? minval : (val > maxval ? maxval : val)) 
     ,max_(maxval) 
     ,min_(minval) 
     ,order_(static_cast<uint16_t>(log10(max_)) + 1) 
{ 
... 

résoudre le problème.

+0

Vous pouvez marquer ceci comme la réponse – cup

+0

Oui, mais je ne suis pas autorisé à le faire jusqu'à 24 heures après l'avoir posté. Il reste encore trois heures. Je vous remercie. – Patxitron