Bonjour la comunauté,
Bon je reviens là dessus pke je sèche sur un pb.
voici le code (minimal) du header :
#ifndef BOUTON_H
#define BOUTON_H
#include <string>
#include <SFML/Graphics.hpp>
class Bouton : public sf::Drawable
{
public:
Bouton(sf::Vector2f, const std::string &, unsigned int, unsigned int = 255, unsigned int = 255, unsigned int = 255); // constructeur
sf::Font m_font;
sf::Vector2f m_position; // position du bouton ("ligne de base" et gauche) / sa fenetre
unsigned int m_rouge; // couleur rouge fond bouton
unsigned int m_vert; // couleur vert fond bouton
unsigned int m_bleu; // couleur bleu fond bouton
sf::Text m_legende; // texte qui apparait sur le bouton
sf::RectangleShape m_rect; // rectangle représentant le bouton
private:
void draw(sf::RenderTarget&, sf::RenderStates = sf::RenderStates::Default) const; // la méthode de la classe virtuelle à implémenter
};
#endif // BOUTON_H
Le CPP associé :
#include "Bouton.h"
Bouton::Bouton(sf::Vector2f position, const std::string &legende, unsigned int htrText, unsigned int rouge, unsigned int vert, unsigned int bleu) : m_position(position), m_rouge(rouge), m_vert(vert), m_bleu(bleu) //constructeur
{
m_font.loadFromFile("Arial.TTF");
m_legende.setFont(m_font);
m_legende.setCharacterSize(htrText);
m_legende.setOutlineThickness(0);
m_legende.setOutlineColor(sf::Color::White);
m_legende.setFillColor(sf::Color::Black);
m_legende.setString(legende);
m_legende.setOrigin(m_legende.getLocalBounds().width / 2, 0);
m_legende.setPosition(position);
m_rect.setOutlineColor(sf::Color::Black);
m_rect.setOutlineThickness(5);
m_rect.setFillColor(sf::Color (m_rouge, m_vert, m_bleu));
m_rect.setSize(sf::Vector2f(m_legende.getLocalBounds().width, m_legende.getLocalBounds().height));
m_rect.setOrigin(m_rect.getLocalBounds().width / 2, 0);
m_rect.setPosition(position.x, position.y + m_legende.getLocalBounds().top);
}
void Bouton::draw(sf::RenderTarget& fenetre, sf::RenderStates) const
{
fenetre.draw(m_rect);
fenetre.draw(m_legende);
}
J'ai mis les variable en "Public", je sais c'est mal, mais c'est évidement provisoire.
Ensuite j'ai une classe fenêtre qui est composée de la classe bouton. les boutons sont placés dans un vector (le nombre de bouton étant variable d'une instance de fenêtre à l'autre).
Le header de la classe fenetre :
#ifndef FENETRE_H
#define FENETRE_H
#include <iostream>
#include <string>
#include <vector>
#include <SFML/Graphics.hpp>
#include "Bouton.h"
class Fenetre
{
public:
Fenetre(const std::string &, const sf::Vector2u &, unsigned int); // constructeur
Fenetre(const std::string &titre, const sf::VideoMode &Mode, unsigned int numero); // constructeur
~Fenetre();
// methode
void efface(); // efface le contenu de la fenêtre
void dessine(sf::Drawable &drawable); // dessine un objet "dessinable"
void affiche(); // affiche le contenu de la fenêtre
void evenement(); // gère les événement et met à jour la fenêtre
void ouvre(unsigned int); // ouvre la fenêtre
void configure(const std::string &titre, const sf::Vector2u &taille, unsigned int); // configuration de la fenêtre (titre, taille et n° d'ordre d'ouverture)
void addBouton(sf::Vector2f, std::string, unsigned int, unsigned int = 255, unsigned int = 255, unsigned int = 255); // ajoute un bouton à la fenêtre (position et texte)
void ferme(); // ferme la fenêtre
bool fini(); // retourne le statut ouvert ou ferme de la fenêtre
bool getEtatBouton(unsigned int); // retourne l'état du bouton n° uint de la fenêtre
// attribut - membre
sf::RenderWindow m_fenetre; // fenêtre crée par la classe
sf::Vector2u m_taille; // taille de la fenêtre
std::string m_titre; // titre de la fenêtre
unsigned int m_bpp; // nb de bit par pixel
unsigned int m_no; // numéro d'ordre de fenêtre (ordre d'ouverture)
bool m_fini; // statut ouvert / fermé de la fenêtre
unsigned int m_nbBouton; // nombre de bouton de la fenêtre
std::vector <Bouton> m_vBouton; // vecteur contenant les boutons de la fenêtre
std::vector <bool> m_vEtatBouton; // vecteur contant l'état des boutons
sf::Vector2u m_sPos; // position de la souris
private:
};
#endif // FENETRE_H
Et le CPP qui implémente :
#include "Fenetre.h"
Fenetre::Fenetre(const std::string &titre, const sf::Vector2u &taille, unsigned int numero) // c(a)stor
{
configure(titre, taille, numero);
}
Fenetre::Fenetre(const std::string &titre, const sf::VideoMode &Mode, unsigned int numero) // constructeur
{
configure(titre, sf::Vector2u(Mode.width, Mode.height), numero);
}
void Fenetre::configure(const std::string &titre, const sf::Vector2u &taille, unsigned int numero)
{
m_titre = titre;
m_taille = taille;
m_no = numero;
m_fini = false;
ouvre(numero);
m_bpp = 32;
}
Fenetre::~Fenetre(){ ferme();}
void Fenetre::addBouton(sf::Vector2f position, std::string legende, unsigned int htrText, unsigned int rouge, unsigned int vert, unsigned int bleu)
{
Bouton bouton(position, legende, htrText, rouge, vert, bleu);
m_vBouton.push_back(bouton);
m_vEtatBouton.push_back(false);
}
bool Fenetre::getEtatBouton(unsigned int numero)
{
return m_vEtatBouton[numero];
}
void Fenetre::ouvre(unsigned int numero)
{
if(numero == 0) m_fenetre.create(sf::VideoMode::getDesktopMode(), m_titre, sf::Style::Fullscreen);
else m_fenetre.create({m_taille.x, m_taille.y, m_bpp}, m_titre, sf::Style::Default);
}
void Fenetre::ferme()
{
m_fenetre.close();
}
void Fenetre::evenement()
{
// on inspecte tous les evenements de la fenêtre qui ont ete emis depuis la precedente iteration
sf::Event event;
while (m_fenetre.pollEvent(event))
{
// evenement "fermeture demandee" : on ferme la fenêtre
if (event.type == sf::Event::Closed)
{
m_fini = true;
}
// evenement mouseclick
if (event.type == sf::Event::MouseButtonPressed)
{
// click gauche...
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
// vérif et mise à jour des boutons fenetre (cliqué ou non) ?
for(unsigned int i = 0; i < m_vBouton.size(); i++)
{
m_sPos.x = sf::Mouse::getPosition(m_fenetre).x;
m_sPos.y = sf::Mouse::getPosition(m_fenetre).y;
m_vBouton[i].active(m_sPos);
}
}
}
// evenement bouton relache
if (event.type == sf::Event::MouseButtonReleased)
{
// activation action lié au bouton ?
for(unsigned int i = 0; i < m_vBouton.size(); i++)
{
m_sPos.x = sf::Mouse::getPosition(m_fenetre).x;
m_sPos.y = sf::Mouse::getPosition(m_fenetre).y;
m_vBouton[i].desactive(m_sPos);
m_vEtatBouton[i] = true;
}
}
}
}
void Fenetre::efface()
{
for(unsigned int i = 0; i < m_vBouton.size(); i++)
{
m_vEtatBouton[i] = false;
}
m_fenetre.clear(sf::Color::Black);
}
void Fenetre::dessine(sf::Drawable &drawable)
{
m_fenetre.draw(drawable);
}
void Fenetre::affiche()
{
for(unsigned int i = 0; i < m_vBouton.size(); i++)
{
m_fenetre.draw(m_vBouton[i]);
}
m_fenetre.display();
}
bool Fenetre::fini()
{
return this -> m_fini;
}
Le pb c'est que ça compile...
Mais lorsque j'instancie une fenetre depuis le main() que j'y ajoute un bouton et que je lance une boucle while "fenetre ouverte", le code plante lors de l'appel au dessin du bouton.
m_fenetre.draw(m_vBouton[i]);
dans Fenetre::affiche() et je suis pas capable de comprendre pourquoi... Je suspecte une mauvaise définiton de la classe bouton héritant de la classe vrtuelle sf::drawable mais je sèche sur le debogage.
En grattant encore un peu je me suis rendu compte que m_rect s'affiche mais pas m_legende.
void Bouton::draw(sf::RenderTarget& fenetre, sf::RenderStates) const
{
fenetre.draw(m_rect);
fenetre.draw(m_legende);
}
m_legende est pourtant un sf::Text défini par le constructeur du bouton.
Une idée ?
Rick.
P.S : DSL pour le code "en vrac", j'ai essayé mais ce n'est pas facile de faire un code "minimal"