Page 1 sur 1

Comment gérer une fenêtre dans un thread

Publié : dim. 23/mars/2014 21:08
par Lord Nelson
Salut,

J'ai fais des recherches mais qui n'ont rien donné et les choses on l'air d'avoir changé.
Quel est la bonne méthode pour gérer une fenêtre dans un thread svp ?

Je voudrait ouvrir une fenêtre et qu'elle se gère seule dans un thread et pas dans le code principal car dans le code
principale il va y avoir des commandes qui lui serons envoyé pour pouvoir interagir avec cette fenêtre.

Ensuite du code principale j’interagis cette fenêtre et les gadget qui y sont.

Schéma si je me trompe pas:

Code secondaire ou sont toutes les commandes et la gestion de cette fenêtre et des gadget et tout le tralala
Code Principale (Fichier 1, D’où je lance la fenêtre et la gère d'ici)

Suis-je assez clair dans ma demande ?

Re: Comment gérer une fenêtre dans un thread

Publié : dim. 23/mars/2014 21:15
par majikeyric
C'est plutôt une fenêtre qui gère un thread non ?

C'est la fenêtre qui crée le thread, qui lui va faire sa tache en parallèle de la gestion de la boucle d'évènements.

(c'est comme ça que je l'ai fait en tous cas)

Re: Comment gérer une fenêtre dans un thread

Publié : dim. 23/mars/2014 21:55
par Lord Nelson
Bha si tu pouvais faire voir comment tu procède.
Je suis un peut perdus là moi :?

Dans l'aide il est bien dis que:
Note: Une fenêtre ne devrait pas être ouverte dans un thread, car il y a une limitation sur OS X et Linux. Une erreur débogueur sera levée. Quand une fenêtre est ouverte dans un thread, le thread doit appeler WindowEvent() ou WaitWindowEvent() dans une boucle pour gérer les évènements pour cette fenêtre, car les évènements des fenêtres sont propres à chaque thread.
Or il est aussi dit que:
Note: La boucle d'événements de la fenêtre ne doit pas être traitée dans un thread, car il y a une limitation sur OS X et Linux. Une erreur du débogueur sera soulevée.
Alors moi plus rien comprendre là :?
Comment ont fais alors :?:

Re: Comment gérer une fenêtre dans un thread

Publié : dim. 23/mars/2014 22:31
par nico
Pourquoi tu veux créer une fenêtre dans un autre thread ?, pourquoi ça ne vas pas le faire dans le thread principal?

Re: Comment gérer une fenêtre dans un thread

Publié : dim. 23/mars/2014 23:24
par Lord Nelson
Pourquoi tu veux créer une fenêtre dans un autre thread ?, pourquoi ça ne vas pas le faire dans le thread principal?
Je sais pas trop comment faire en faite alors je vais donner quelques petit détail pour que vous puissiez m’aiguiller

Je voudrait faire une espèce de console (Non pas une console comme vous l'entendez mais ça y ressemble dans le font)
Une fenêtre avec un éditeur RTF dedans.

Donc ya un code ou l'utilisateur va taper ces commandes pour interagir avec la dite console (Écrire / entrer du texte, afficher des images, etc)
Et donc il dois y avoir le code qui permet de gérer cette fenêtre et les événements que l'utilisateur va entrer mais ça l'utilisateur ne le verra pas, il verras que son code à lui !

Donc je suppose qu'il faut un thread pour gérer la fenêtre et attendre que quelque choses se passe ou que l'utilisateur envoie une commande de par son code
Faut imaginer une console comme la console de PureBasic, on ne gère pas la fenêtre de la console, on l'ouvre, on affiche du texte etc

La c'est pareil sauf que c'est pas une console a proprement parler, je dis console car on va faire de même, interagir avec cette fenêtre en y écrivant du texte, des images, etc
Exemple:

Code : Tout sélectionner

OuvrirConsoleGraphique()
Ecrire("Blablabla")
La fenêtre s'ouvre et affiche Blablabla et c'est tout pour cet exemple.
Donc la gestion du code de la fenêtre on ne le voie pas, on ne voie rien, enfin l'utilisateur quoi, lui il s'occupe juste de taper ces commandes et voilà.

Je sais pas si je suis clair :?

Re: Comment gérer une fenêtre dans un thread

Publié : dim. 23/mars/2014 23:39
par Backup
si si !

Re: Comment gérer une fenêtre dans un thread

Publié : lun. 24/mars/2014 6:52
par graph100
écoute, en faisant une recherche dans mes code j'ai trouvé les 2 suivants :

Désactive le débuggeur pour les lancer sinon l'erreur mentionnée dans l'aide est levée.

Code : Tout sélectionner

;{ init

Structure thread_id
   thread_id.l
   
   valeur.l
EndStructure



Global IS_end.b = 0

compteur = 0



Global NewList thread_id.thread_id()


;}



Procedure Thread_Compteur(*id.thread_id)
   If *id\valeur > 5
      Title$="Thread Timeout"
      Y = 60
   Else
      Title$="Thread Timer"
      Y = 120
   EndIf
   
   thread_window = OpenWindow(#PB_Any, 200, Y, 200, 25, Title$, #PB_Window_Tool)
   
   If thread_window
      thread_textgadget = TextGadget(#PB_Any, 5, 5, 90, 20, "", #PB_Text_Border)
      
   Else
      ProcedureReturn
   EndIf
   
   time = ElapsedMilliseconds()
   
   Repeat
      event = WaitWindowEvent(50)
      
      SetGadgetText(thread_textgadget, Str(ElapsedMilliseconds() - time) + "ms")
      
      
      If ElapsedMilliseconds() - time > *id\valeur * 1000
         event = #PB_Event_CloseWindow
      EndIf
      
   Until event = #PB_Event_CloseWindow Or IS_end
   
   If IS_end = 0
      ChangeCurrentElement(thread_id(), *id)
      DeleteElement(thread_id())
   EndIf
   
   CloseWindow(thread_window)
   
EndProcedure



If OpenWindow(0, 420, 100, 200, 30, "Test", #PB_Window_SystemMenu)
   TextGadget(0, 5, 5, 190, 20, "", #PB_Text_Border)
   
   AddWindowTimer(0, 0, 1000) ; ajoute un timer à la fenetre 0, tick toutes les 1 sec
Else
   MessageRequester("Erreur", "Impossible de lancer la fenetre principale")
EndIf




Repeat
   event = WaitWindowEvent()
   
   
   If event = #PB_Event_Timer And EventTimer() = 0
      compteur + 1
      
      SetGadgetText(0, Str(compteur) + "s")
      
      If compteur = 5
         *current.thread_id = AddElement(thread_id())
         
         *current\valeur = 3
         *current\thread_id = CreateThread(@Thread_Compteur(), *current)
         
      ElseIf compteur = 10
         *current.thread_id = AddElement(thread_id())
         
         *current\valeur = 10
         *current\thread_id = CreateThread(@Thread_Compteur(), *current)
         
         
         compteur = 0
      EndIf
   EndIf
   
   
Until event = #PB_Event_CloseWindow

IS_end = #True

ForEach thread_id()
   *current.thread_id = @thread_id()
   WaitThread(*current\thread_id)
Next

End

Code : Tout sélectionner

;{ variables Globales, structures

Global EXIT.b = #False
Define.l TT_Aide

;}


Procedure OpenAide(fen_principale.l)
	
	ww_aide = OpenWindow(#PB_Any, WindowX(fen_principale) - 215, WindowY(fen_principale), 200, 400, "Ma fenêtre d'aide", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_Tool)
	If ww_aide
		
	EndIf
	
	
	Repeat
		event = WaitWindowEvent(200)
		
		
	Until event = #PB_Event_CloseWindow Or EXIT
	
	
	CloseWindow(ww_aide)
	
EndProcedure



ww_principale = OpenWindow(#PB_Any, 0, 0, 500, 400, "Ma fenêtre principale", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_MinimizeGadget)
If ww_principale
	gg_button_aide = ButtonGadget(#PB_Any, 10, 10, 200, 20, "Ouvrir la fenetre d'aide")
	
EndIf





Repeat
	event = WaitWindowEvent()
	
	If event = #PB_Event_Gadget
		Select EventGadget()
			Case gg_button_aide
				If IsThread(TT_Aide) = 0
					TT_Aide = CreateThread(@OpenAide(), ww_principale)
				EndIf
				
				
		EndSelect
	EndIf	
	
Until event = #PB_Event_CloseWindow

EXIT = #True

CloseWindow(ww_principale)

If IsThread(TT_Aide)
	WaitThread(TT_Aide, 1000)
EndIf


End


Cependant si je devais reprogrammer ce genre de truc maintenant, je ne m'y prendrais pas de cette façon là.
Regarde avec l'utilisation de la commande EventWindow().

Et ne créé pas tes fenêtres depuis le thread, mais plutot depuis le programme principal.
Simplement, gère les ensuite depuis le thread.

Re: Comment gérer une fenêtre dans un thread

Publié : lun. 24/mars/2014 9:36
par MLD
Salut

Tu peux parfaitement crée une fenêtre et utilisé sa boucle d'évênement dans une procédure. la seule précaution a prendre est que la boucle soit du type : Repeat: ForEver. La sortie de la boucle se faisant par un Break.
J'utilise ceci dans des programmes multi-fenêtres. Donc sans thread.

Re: Comment gérer une fenêtre dans un thread

Publié : lun. 24/mars/2014 10:01
par Lord Nelson
Merci beaucoup pour vos réponses :)
J'ai procédé comme tel, vous en pensez quoi ?

Si j'ai zappé des choses, je m'en excuse d’avance :)

Code Secondaire qui gère la fenêtre et tout le reste, nommer le avec l’extension PBI:

Code : Tout sélectionner

Structure StructureFenetre
  
  NumeroFenetre.i
  X.i
  Y.i
  Largeur.i
  Hauteur.i
  Titre.s
  Option.i
  
EndStructure

Procedure OuvertureFenetre(*Parametres.StructureFenetre)
  
  If OpenWindow(*Parametres \ NumeroFenetre, *Parametres \ X, *Parametres \ Y, *Parametres \ Largeur, *Parametres \ Hauteur, *Parametres \ Titre, *Parametres \ Option)
    
    Repeat
      
      Event = WaitWindowEvent()
      
    Until Event = #PB_Event_CloseWindow
    
  Else
    MessageRequester("Erreur lors de l'ouverture de la fenêtre", "Impossible d'ouvrir la fenêtre n° " + Str(NumeroFenetre), #MB_ICONERROR)
    
  EndIf
  
EndProcedure

Procedure OuvrirFenetre(NumeroFenetre, X, Y, Largeur, Hauteur, Titre$, Option)
  
  *Parametres.StructureFenetre = AllocateMemory(SizeOf(StructureFenetre))
  
  *Parametres \ Hauteur = NumeroFenetre
  *Parametres \ X = X
  *Parametres \ Y = Y
  *Parametres \ Largeur = Largeur
  *Parametres \ Hauteur = Hauteur
  *Parametres \ Titre = Titre$
  *Parametres \ Option = Option
  
  NumeroThreadFenetre = CreateThread(@OuvertureFenetre(), *Parametres)
  
EndProcedure
Code Principale, c'est là ou l'utilisateur interagir avec la fenêtre, nommer le avec l’extension PB:

Code : Tout sélectionner

XIncludeFile "Votre Code.Pbi"

Enumeration 
  #Fenetre
EndEnumeration

OuvrirFenetre(#Fenetre, 0, 0, 800, 600, "Console", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
Delay(10000)
Reste plus qu'à comme qui dirait :)

Re: Comment gérer une fenêtre dans un thread

Publié : lun. 24/mars/2014 17:10
par graph100
c'est une façon de faire. Très bien la structure pour passer les paramètres au thread.

Re: Comment gérer une fenêtre dans un thread

Publié : lun. 24/mars/2014 17:16
par Lord Nelson
Merci, j'ai pris l'exemple super utile tiré de l'aide de PB :)

Re: Comment gérer une fenêtre dans un thread

Publié : mar. 25/mars/2014 9:55
par Mesa
L'aide est en cours de mis à jour mais ne sera visible que dans la version 5.30 de PB (dans 2 ans). Je posterai une version intermédiaire entre-temps, peut-être cet été.

Il faut lire.
Note: Une fenêtre ne devrait pas être ouverte dans un thread, car il y a une limitation sur OS X et Linux. Une erreur débogueur sera levée.
Même s'il est possible de mettre une fenêtre dans un thread, ça ne concerne que Windows et en plus le bon fonctionnement n'est pas garantie.

Il est donc conseillé de repenser son code afin de n'avoir qu'une seule boucle principale qui gère toutes les fenêtres ( en utilisant : les fenêtres-filles, mdigadget, hidewindow(), #PB_Window_Invisible, ...), c'est plus prudent.

M. .

Re: Comment gérer une fenêtre dans un thread

Publié : lun. 31/mars/2014 15:49
par Lord Nelson
J'ai effacé le sujet en double, je poste tellement que je me souvient même plus de se que je poste :oops:
Si ma façon de coder est correcte, je me demande pourquoi PB n'est pas ok lui !
OpenWindow() ne peut être appelée qu'à partir du thread principale.
WindowEvent() et WaitWindowEvent() ne peuvent être appelées qu'à partir de thread principale.
Et comme dis l'aide aussi, tout comme Mesa:
Note: Une fenêtre ne devrait pas être ouverte dans un thread, car il y a une limitation sur OS X et Linux. Une erreur débogueur sera levée.
Je ne sais pas comment faire :|

Je suis obligé de désactiver le Débogueur pour que cella fonctionne !
Ceci m’embête car sans le débogueur, pas facile de gérer son code :|

Ma façon fonctionne mais n'est pas correcte et qui plus est quand je veux ajouter des gadgets par la suite à la fenêtre, rien ne va plus !
Qu'elle est la bonne façon de faire svp ?