IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

GTK+ Discussion :

[gtkmm] thread et protection des widget


Sujet :

GTK+

  1. #1
    Débutant Avatar de Rniamo
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    508
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 508
    Points : 162
    Points
    162
    Par défaut [gtkmm] thread et protection des widget
    bonjour,

    je souhaite utilisé un thread qui réactualise mon interface (un petit explorateur) mais je n'arrive pas à le faire sans synchroniser celui-ci par la fonction join() qui me fait perdre l'intérêt du thread.

    Sous gtk/gdk j'ai vu qu'il y avait les fonction gdk_thread_enter/leave mais sous gtkmm/gdkmm il n'y a rien d'équivalent.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    void ListeCourant::listeDossierEff(void)
    {
    	static Glib::RefPtr<Gdk::Pixbuf> pixF=Gdk::Pixbuf::create_from_file(fen.getTheme()+ICON_FICHIER,TAILLE_ICON_PETITE,TAILLE_ICON_PETITE,true);
    	static Glib::RefPtr<Gdk::Pixbuf> pixD=Gdk::Pixbuf::create_from_file(fen.getTheme()+ICON_DOSSIER,TAILLE_ICON_PETITE,TAILLE_ICON_PETITE,true);
    	string repCourant=fen.getCourant();
    	try
    	{
    		Glib::Dir dir(repCourant);
     
    		string name=dir.read_name();
    		int id=0;
    		while(!name.empty())
    		{
    			if (name.length() && name[0] != '.')
    			{
    				string path=Glib::build_filename(repCourant,name);
     
    				Glib::ustring nom=Glib::filename_to_utf8(name);
    				if (Glib::file_test(path,Glib::FILE_TEST_IS_DIR))
    				{
    					TreeModel::Row row=*(this->refTreeModel->append());
    					row[this->treeModel.pixbuf]=pixD;
    					row[this->treeModel.chemin]=repCourant;
    					row[this->treeModel.nom]=nom;
    					row[this->treeModel.type]="Dossier";
    					row[this->treeModel.taille]="";
    					row[this->treeModel.id]=id++;
     
    					Dossier d(nom);
    					fen.getListeDossier().push_back(d);
    					fen.getListeDossier().sort(Dossier::tri);
    				}
    				else if (Glib::file_test(path,Glib::FILE_TEST_IS_REGULAR) && fichierTmp(path) && formatOK(path))
    				{
    					TreeModel::Row row=*(this->refTreeModel->append());
    					int taille=utile::taille(path);
    					Fichier f(fen.getCourant(),nom,taille);
    					if(f.getPixbuf())
    					{
    						f.setPixbufIconPetite(f.getPixbuf()->scale_simple(TAILLE_ICON_PETITE,TAILLE_ICON_PETITE,Gdk::INTERP_BILINEAR));
    						row[this->treeModel.pixbuf]=f.getPixbufIconPetite();
    					}
    					else
    						row[this->treeModel.pixbuf]=pixF;
     
    					row[this->treeModel.chemin]=repCourant;
    					row[this->treeModel.nom]=f.getNom();
    					row[this->treeModel.type]="Fichier";
    					if (taille<0)
    						row[this->treeModel.taille]="";
     
    					else if (taille/1048576>0)
    						row[this->treeModel.taille]=utile::all2string(taille/1048576)+","+utile::all2string(taille-(taille/1048576)*1048576)+" Mo";
    					else if (taille/1024>0)
    						row[this->treeModel.taille]=utile::all2string(taille/1024)+","+utile::all2string(taille-(taille/1024)*1024)+" ko";
    					else
    						row[this->treeModel.taille]=utile::all2string(taille)+" o";
     
    					row[this->treeModel.id]=id++;
     
    					fen.getListeFichier().push_back(f);
    					fen.getListeFichier().sort(Fichier::tri);
    				}
    			}
    			name=dir.read_name();
    			fen.getGLScene().queue_draw();
    		}
    		fen.getGLScene().queue_draw();
    	}
    	catch(const Glib::FileError& ex)
    	{
    		std::cout << ex.what() << std::endl;
    	}
    }
     
    void ListeCourant::liste(bool clear)
    {	
    	if (clear)
    		refTreeModel->clear();		
    	fen.supprimeListes();
     
    	if(!Glib::thread_supported())
    		Glib::thread_init();
     
    	try
    	{
    		thread=Glib::Thread::create(sigc::mem_fun(*this,&ListeCourant::listeDossierEff),true);
    		thread->join(); // ICI le join()
    	}
    	catch(Glib::ThreadError& e)
    	{
    		cout << e.what() << endl;
    	}
    	catch(Glib::Thread::Exit& e) {}
    }

  2. #2
    Débutant Avatar de Rniamo
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    508
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 508
    Points : 162
    Points
    162
    Par défaut
    j'ai essayé les foncitons :

    gdk_thread_enter/leave/flush() mais rien n'y fait. Je doit verrouiller un treeview mais je ne sais pas comment faire, un mutex ne suffit pas vu que le raffraichissement est automatique.

  3. #3
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Points : 1 633
    Points
    1 633
    Par défaut
    Tu peux pas faire en sorte d'appeler les fonctions gtk+ uniquemnet dans le thread principal ? Par ex en faisant tout le travail sauf l'affichage dans ton thread et en utilisant g_idle_add (ou une GAsyncQueue ou toute autre méthode plus appropriée en gtkmm) pour dire à ton thread principal "ok, il faut que tu affiches ça et ça" ?

  4. #4
    Débutant Avatar de Rniamo
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    508
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 508
    Points : 162
    Points
    162
    Par défaut
    en fait le thread remplacer un g_idle.

    Son intérêt est qu'il est fait en même temps que le programme principal tourne.

    Je liste les fichier d'un répertoire et je raffraichit le treeview en même temps (dans le thread). Je ne vois aps comment faire autrement.

  5. #5
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Points : 1 633
    Points
    1 633
    Par défaut
    Tu peux avoir un callback de g_idle_add qui sait ajouter une colonne à ton treeview par exemple. Comme ça tu fais les IOs dans un thread (j'imagine que cette partie là était lente donc que tu l'as déplacée) et les changements de treeview dans le thread principal (via le g_idle_add)

  6. #6
    Débutant Avatar de Rniamo
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    508
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 508
    Points : 162
    Points
    162
    Par défaut
    c'est ce que je veux faire mais g_idle est lancer quand gtk ne fait rien, donc en fait il faudrait que je fasse un thread + g_idle ?

    edit :en fait je ne vois pas où mettre g_idle
    edit 2 : il n'y a pas moyen de rendre gtkmm thread-safe ?
    edit 3 :
    One common way to do this is to have non-GUI threads send requests to the GUI thread via a pipe. The pipe is hooked into the main glib event loop used by GTK.
    En clair ça veut dire quoi ?

  7. #7
    Débutant Avatar de Rniamo
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    508
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 508
    Points : 162
    Points
    162
    Par défaut
    en fait avec gdk_thread_enter/leave ça marche mais j'ai un autre soucis :

    je fais ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if(f.getPixbuf() && !f.getPixbufIconPetite())
    						f.setPixbufIconPetite(f.getPixbuf()->scale_simple(TAILLE_ICON_PETITE,TAILLE_ICON_PETITE,Gdk::INTERP_BILINEAR));
    					if (f.getPixbufIconPetite())
    						row[this->treeModel.pixbuf]=f.getPixbufIconPetite();
    					else
    						row[this->treeModel.pixbuf]=pixF;
    avec f de type Fichier :

    Fichier.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    #include "Fichiers.hh"
     
    const int Fichier::TAILLE_PIXBUF=256;
     
    void Fichier::setTex(GLuint n)
    {
    	tex=n;
    }
     
    GLuint Fichier::getTex(void)
    {
    	return tex;
    }
     
    void Fichier::setPixbufIconPetite(Glib::RefPtr<Gdk::Pixbuf> pixbuf)
    {
    	iconPetite=pixbuf;
    }
     
    void Fichier::setPixbufIconGrande(Glib::RefPtr<Gdk::Pixbuf> pixbuf)
    {
    	iconGrande=pixbuf;
    }
     
    Glib::RefPtr<Gdk::Pixbuf> Fichier::getPixbufIconGrande(void)
    {
    	return iconGrande;
    }
     
    Glib::RefPtr<Gdk::Pixbuf> Fichier::getPixbufIconPetite(void)
    {
    	return iconPetite;
    }
     
    bool Fichier::isImage(const Glib::ustring& str)
    {
    	int nbExt=4;
    	Glib::ustring extImage[]={"jpg","JPG","png","gif"};
     
    	if (str.size()<=3)
    		return false;
     
    	for(int i=0;i<nbExt;i++)
    	{
    		if (!( (str.substr(str.size()-3)).compare(extImage[i]) ))
    			return true;
    	}
     
    	return false;
    }
     
     
    bool Fichier::isImage(void)
    {
    	Glib::ustring nom(getCheminComplet());
    	return Fichier::isImage(nom);
    }
     
    Glib::ustring Fichier::getCheminComplet()
    {
    	Glib::ustring  s("");
    	if (dossier!="/")
    		s=dossier+"/"+nom;
    	else
    		s=dossier+nom;
    	return s;
    }
     
    bool Fichier::tri(Fichier& f1, Fichier& f2)
    {
    	Glib::ustring str1(""), str2("");
    	f1.getDossier()!="/" ? str1=f1.getDossier()+"/"+f1.getNom() : str1=f1.getDossier()+f1.getNom() ;
    	f2.getDossier()!="/" ? str2=f2.getDossier()+"/"+f2.getNom() : str2=f2.getDossier()+f2.getNom() ;
    	if (str1.compare(str2)<=0)
    		return true;
    	return false;
    }
     
    Glib::RefPtr<Gdk::Pixbuf> Fichier::getPixbuf(void)
    {
    		return pixbuf;
    }
     
    Glib::ustring Fichier::getDossier(void)
    {
    	return this->dossier;
    }
     
    void Fichier::setDossier(const Glib::ustring& d)
    {
    	this->dossier=d;
    }
     
    Glib::ustring Fichier::getNom(void)
    {
    	return this->nom;
    }
     
    void Fichier::setNom(const Glib::ustring& n)
    {
    	this->nom=n;
    }
     
    int Fichier::getTaille(void)
    {
    	return this->taille;
    }
     
    void Fichier::setTaille(int t)
    {
    	this->taille=t;
    }
     
    void Fichier::get(Glib::ustring& d,Glib::ustring& n, int& t)
    {
    	d=this->dossier;
    	n=this->nom;
    	t=this->taille;
    }
     
    void Fichier::set(const Glib::ustring& d, const Glib::ustring& n, int t)
    {
    	this->dossier=d;
    	this->nom=n;
    	this->taille=t;
    }
     
    Fichier::Fichier(const Glib::ustring& d, const Glib::ustring& n, int t) : dossier(d), nom(n), taille(t)
    {
    	Glib::ustring f;
    	d!="/" ? f=d+"/"+n : f=d+n;
    	if (Glib::file_test(f,Glib::FILE_TEST_IS_REGULAR))
    	{
    		try
    		{
    			pixbuf=Gdk::Pixbuf::create_from_file(f,Fichier::TAILLE_PIXBUF,Fichier::TAILLE_PIXBUF,true);
    		}
    		catch(Gdk::PixbufError&)
    		{
    			pixbuf.reset();
    		}
    		catch(Glib::FileError&)
    		{
    			pixbuf.reset();
    		}
    	}
    }
     
    Fichier::Fichier() : dossier(""), nom(""), taille(0)
    {
    }
     
    Fichier::~Fichier()
    {
    	if (iconGrande)
    		glDeleteTextures(1,&tex);
    }
    Fichier.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    #ifndef FICHIERS_HH
    #define FICHIERS_HH
     
    #include <GL/gl.h>
    #include <iostream>
    #include <gtkmm.h>
    #include <string>
    #include <cctype>
    #include <algorithm>
    #include "utile.hh"
     
    using namespace std;
     
    class Fichier
    {
    	private:
    		static const int TAILLE_PIXBUF;
     
    		Glib::ustring typemime;
    		Glib::ustring dossier;
    		Glib::ustring nom;
    		int taille;
    		Glib::RefPtr<Gdk::Pixbuf> pixbuf;
    		Glib::RefPtr<Gdk::Pixbuf> iconPetite;
    		Glib::RefPtr<Gdk::Pixbuf> iconGrande;
    		GLuint tex;
     
    		static bool isImage(const Glib::ustring& str);
     
    	public:
    		Fichier(const Glib::ustring& d, const Glib::ustring& n, int t);
    		Fichier(void);
    		~Fichier(void);
     
    		bool isImage(void);
     
    		void setTex(GLuint n);
    		GLuint getTex(void);
     
    		Glib::ustring getDossier(void);
    		void setDossier(const Glib::ustring& d);
     
    		Glib::ustring getNom(void);
    		void setNom(const Glib::ustring& n);
     
    		int getTaille(void);
    		void setTaille(int t);
     
    		void get(Glib::ustring& d,Glib::ustring& n, int& t);
    		void set(const Glib::ustring& d, const Glib::ustring& n, int t);
     
    		Glib::ustring getCheminComplet(void);
     
    		Glib::RefPtr<Gdk::Pixbuf> getPixbuf(void);
     
    		void setPixbufIconPetite(Glib::RefPtr<Gdk::Pixbuf> pixbuf);
    		Glib::RefPtr<Gdk::Pixbuf> getPixbufIconPetite(void);
     
    		void setPixbufIconGrande(Glib::RefPtr<Gdk::Pixbuf> pixbuf);
    		Glib::RefPtr<Gdk::Pixbuf> getPixbufIconGrande(void);
     
    		static bool tri(Fichier& f1, Fichier& f2);
    };
     
    #endif
    Le problème vient de getPixbufIconGrande().
    ça me renvoie une erreur de segmentation.

  8. #8
    Débutant Avatar de Rniamo
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    508
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 508
    Points : 162
    Points
    162
    Par défaut
    bon les thread avec gtk c'est pas la joie, c'est sûr qu'une solution avec un thread qui ne touche pas à al fenêtre serait pas mal.

    merci teuf13

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Gestion de l'état des widgets Tkinter par des Threads
    Par piokml dans le forum Général Python
    Réponses: 3
    Dernier message: 18/10/2012, 11h00
  2. Gtkmm comment automatiser le rafraichissement des widgets?
    Par Krishna dans le forum Bibliothèques
    Réponses: 0
    Dernier message: 19/07/2009, 14h51
  3. [gtkmm] pointer sur des widgets
    Par MDiabolo dans le forum GTK+ avec C & C++
    Réponses: 0
    Dernier message: 20/03/2008, 12h44
  4. Réponses: 7
    Dernier message: 23/10/2005, 21h52
  5. Désactiver la protection des fichiers systéme
    Par cartonis dans le forum Sécurité
    Réponses: 6
    Dernier message: 13/08/2005, 19h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo