Comment gérer une fenêtre dans un thread

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Lord Nelson
Messages : 355
Inscription : dim. 01/déc./2013 15:29

Comment gérer une fenêtre dans un thread

Message 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 ?
Dernière modification par Lord Nelson le dim. 23/mars/2014 21:36, modifié 1 fois.
Avatar de l’utilisateur
majikeyric
Messages : 602
Inscription : dim. 08/déc./2013 23:19
Contact :

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

Message 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)
Lord Nelson
Messages : 355
Inscription : dim. 01/déc./2013 15:29

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

Message 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 :?:
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

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

Message 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?
Lord Nelson
Messages : 355
Inscription : dim. 01/déc./2013 15:29

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

Message 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 :?
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

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

Message par Backup »

si si !
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

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

Message 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.
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
MLD
Messages : 1124
Inscription : jeu. 05/févr./2009 17:58
Localisation : Bretagne

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

Message 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.
Lord Nelson
Messages : 355
Inscription : dim. 01/déc./2013 15:29

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

Message 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 :)
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

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

Message par graph100 »

c'est une façon de faire. Très bien la structure pour passer les paramètres au thread.
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Lord Nelson
Messages : 355
Inscription : dim. 01/déc./2013 15:29

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

Message par Lord Nelson »

Merci, j'ai pris l'exemple super utile tiré de l'aide de PB :)
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

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

Message 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. .
Lord Nelson
Messages : 355
Inscription : dim. 01/déc./2013 15:29

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

Message 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 ?
Répondre