Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Affichage sf::Text retourné d'une fonction  (Lu 71 fois)

0 Membres et 1 Invité sur ce sujet

Rick_Cplusplus

  • Newbie
  • *
  • Messages: 33
    • Voir le profil
    • E-mail
Affichage sf::Text retourné d'une fonction
« le: Août 06, 2019, 03:14:48 pm »
Bonjour la communauté,

En raffinant au maximum mon problème d'affichage de sf::text de mon dernier post , j'arrive à ceci :
#include <iostream>
#include <SFML/Graphics.hpp>
#include "Fenetre.h"

sf::Text dessineText(unsigned int const htr = 20)
{
    sf::Font font;
    font.loadFromFile("Arial.ttf");
    std::string duTexte("essai");
    sf::Text texte(duTexte, font, htr);
    return texte;
}

int main()
{
    Fenetre *pFenetre = new Fenetre("Ma fenetre", sf::Vector2u (1024, 768));

    sf::Text texte;
    texte = dessineText();

    while(!pFenetre -> fini())
    {
        pFenetre -> evenement();
        pFenetre -> efface();
        pFenetre -> dessine(texte); //<=  là il se perd en conjectures (et moi aussi)...
        pFenetre -> affiche();
    }

    delete pFenetre;
    return 0;
}

Le code de ma classe fenêtre ne semble pas en cause.
A tout hasard, voici le header :
#ifndef FENETRE_H
#define FENETRE_H

#include <string>
#include <SFML/Graphics.hpp>

class Fenetre
{
    public:
        Fenetre(const std::string &, const sf::Vector2u &);
        ~Fenetre();

        // Methode
        void efface(); // efface le contenu de la fenetre
        void dessine(sf::Drawable &drawable); // dessine un objet dessinable
        void affiche(); // affiche le contenu de la fenetre
        void evenement(); // gère les evenemente et met à jour la fenetre
        bool fini(); // retourne le statut ouvert ou ferme de la fenetre

    private:
        //Methode
        void configure(); // configuration de la fenêtre (titre et taille)
        void ferme(); // ferme la fenêtre

        // Attribut
        sf::RenderWindow m_fenetre; // fenêtre créé 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
        bool m_fini; // statut ouvert / fermé de la fenêtre
};

#endif // FENETRE_H

Et le CPP associé :
#include "Fenetre.h"

Fenetre::Fenetre(const std::string &titre, const sf::Vector2u &taille) :
m_fenetre(), m_taille(taille), m_titre(titre), m_bpp(32), m_fini(false)
{
    configure();
}

Fenetre::~Fenetre()
{
        ferme();
}

void Fenetre::configure()
{
    m_fenetre.create({m_taille.x, m_taille.y, m_bpp}, m_titre, sf::Style::Default);
    return;
}

void Fenetre::ferme()
{
    m_fenetre.close();
    return;
}

void Fenetre::evenement()
{
    sf::Event event;
    while (m_fenetre.pollEvent(event))
    {
        if (event.type == sf::Event::Closed)
        {
            m_fini = true;
        }
    }
    return;
}

void Fenetre::efface()
{
    m_fenetre.clear(sf::Color::Black);
    return;
}

void Fenetre::dessine(sf::Drawable &drawable)
{
    m_fenetre.draw(drawable);
    return;
}

void Fenetre::affiche()
{
    m_fenetre.display();
    return;
}

bool Fenetre::fini()
{
    return this -> m_fini;
}

Le code compile (hélas :'( ) mais l’exécution plante.
En usant du debugger pas à pas, la ligne fatale est celle appelant la méthode "dessine" qui tente d'exécuter :
m_fenetre.draw(drawable);

Le debugger indique alors :
#0 0x69162e5c   std::less<unsigned int>::operator() (this=0x28fb44, __x=<error reading variable>, __y=@0x28f9b0: 20) (C:/Dev/MinGW32-PosixDwarf730r0/lib/gcc/i686-w64-mingw32/7.3.0/include/c++/bits/stl_function.h:386)

Ce qui pour moi est inintelligible..
Voilà, si quelqu'un a une idée, moi je sèche... :-\

Rick.

G.

  • Hero Member
  • *****
  • Messages: 1392
    • Voir le profil
Re: Affichage sf::Text retourné d'une fonction
« Réponse #1 le: Août 06, 2019, 05:27:23 pm »
It is important to note that the sf::Text instance doesn't copy the font that it uses, it only keeps a reference to it. Thus, a sf::Font must not be destructed while it is used by a sf::Text (i.e. never write a function that uses a local sf::Font instance for creating a text).
Ton sf::Font est local à ta fonction dessineText et est donc détruit à la fin de celle-ci.
Et on n'est pas même sûr que font.loadFromFile("Arial.ttf"); ait fonctionné.
J'ai pas lu si le reste est faux.

Rick_Cplusplus

  • Newbie
  • *
  • Messages: 33
    • Voir le profil
    • E-mail
Re: Affichage sf::Text retourné d'une fonction
« Réponse #2 le: Août 07, 2019, 05:36:30 pm »
Aaaah voilà ; le mystère se dissipe... :D
Effectivement j'ai cherché partout sauf sur la doc de sf::Font ! :-\
Merci pour ce "rappel".  ;)
Du coup,  il serait peut être pertinent :

1) de faire de "font" une variable statique public dans chaque classe ayant un attribut de type sf::Text et d’initialiser cette variable statique avec une méthode (statique elle aussi) vérifiant que la font est bien là ou on l'appelle.

Ou bien

2) de faire de "font" une variable statique initialisée de même dans un namespace et d'inclure le namespace dans chaque header de classe ayant un attribut de type sf:Text pour appeler la variable qd nécessaire.

Ou bien

3) faire autrement... Mais quoi ?

Qu'est-ce qui se fait d'habitude en "bonne pratique" ?

Rick.

G.

  • Hero Member
  • *****
  • Messages: 1392
    • Voir le profil
Re: Affichage sf::Text retourné d'une fonction
« Réponse #3 le: Août 07, 2019, 06:27:44 pm »
Tu peux en faire un membre de ta Fenetre

Rick_Cplusplus

  • Newbie
  • *
  • Messages: 33
    • Voir le profil
    • E-mail
Re: Affichage sf::Text retourné d'une fonction
« Réponse #4 le: Août 07, 2019, 08:12:04 pm »
Bien après un (long) processus essai erreur j'arrive à ça :

Le header :
#ifndef FENETRE_H
#define FENETRE_H

#include <string>
#include <SFML/Graphics.hpp>

class Fenetre
{
    public:

        // Constructeur & Destructeur
        Fenetre(const std::string &, const sf::Vector2u &);
        ~Fenetre();

        // methode statique
        static bool chargeFont(std::string const &);

        //Accesseurs
...

        // methode
...

    private:
        // attribut
        static sf::Font fontFenetre; // Font des sf::Text des fenetres
...

};

#endif // FENETRE_H

le CPP :
#include "Fenetre.h"

sf::Font Fenetre::fontFenetre; // declaration de la font

Fenetre::Fenetre(const std::string &titre, const sf::Vector2u &taille) :
...
{

}

Fenetre::~Fenetre()
{

}

bool Fenetre::chargeFont(std::string const & fichier) // Methode statique
{
    return (Fenetre::fontFenetre.loadFromFile(fichier.c_str()));
}

 

Et dans le main :
#include <SFML/Graphics.hpp>
#include "Fenetre.h"

int main()
{
    // chargement d'une font (et verif succès)
    if(!Fenetre::chargeFont("Arial.ttf"))
    {
        std::cerr << "Fichier Arial.ttf introuvable" << std::endl;
        return -1;
    }
...
return 0;
 

Ainsi toutes les fenêtres crées ont la même font et Fenêtre::fontFenetre reste "vivant" au long de l'application. :)
Y'a peut être mieux mais je n'ai pas trouvé. ;)

Rick.

Rick.
« Modifié: Août 09, 2019, 04:00:16 pm par Rick_Cplusplus »