Progress bar: Probleme d'affichage. [Résolu]

yayou49 7 Messages postés lundi 17 février 2014Date d'inscription 30 mars 2015 Dernière intervention - 19 mars 2015 à 16:43 - Dernière réponse : yayou49 7 Messages postés lundi 17 février 2014Date d'inscription 30 mars 2015 Dernière intervention
- 30 mars 2015 à 11:39
Bonjour,

Pour faire simple, J'ai une Form qui exécute du code chronophage et je souhaiterai ajouter une Progress bar pendant le temps d'exécution.
Mon problème c'est que la Progress bar ne se met à jour qu'a la fin de l'exécution du long traitement.

J'ai vu ici et là que l'utilisation d'un BackgroundWorker pouvait résoudre le problème. Malheureusement, je ne m'en sort pas et j'aurai donc besoin de votre aide.

Une petite précision: je ne souhaite pas faire évoluer la progress bar au fils du temps mais juste l'afficher avec une valeur max(-1) pour visualiser le petit mouvement auto-généré par cette progress bar tant qu'elle n'est pas au max (ce qui explique pourquoi j'ai indiqué max(-1)).

Posons les bases de l'exemple:

J'ai une Form nommée Form1
Sur cette form, j'ai:
- un bouton nommé "BtGo"
- une progress bar nommée "Pb" avec visible = false.


Voici le code qui correspond à ce que je souhaiterai faire:

Public Class Form1

Private Sub BtGo_Click(sender As System.Object, e As System.EventArgs) Handles BtGo.Click

'Appel du démarrage de la progress bar (parametre = True)
Barre(True)


'// appel à la sub de traitement chronophage
'//
'//

'Appel de l'arret de la progress bar (parametre = False)
Barre(False)

End Sub
Private Sub Barre(ByVal Start As Boolean)

If Start = True Then

'*** Paramétrage de la Progress Bar ***
Pb.Minimum = 0
Pb.Maximum = 5000
Pb.Value = 4999 'Valeur maximum - 1
Dim Pos As New System.Drawing.Point
Pos.X = 0
Pos.Y = 10
Pb.Location = Pos
'on defini la largeur de la barre, égale à la largeur de la form.
Pb.Width = Me.Width
Pb.Visible = True 'parce que la progress bar est visible(false) dans la form


'et c'est là que je ne sais plus quoi faire car ma progress bar ne s'affichera complete qu'a la fin du traitement chronophage............

Else
Pb.Visible = False
End If

End Sub

End Class


Voila, j'espère que mon problème est expliqué clairement et que vos réponses pourront éclairer ma lanterne.

Merci par avance.

Yannick
Afficher la suite 

Votre réponse

7 réponses

guatto 12 Messages postés jeudi 19 mars 2015Date d'inscription 1 juin 2016 Dernière intervention - 19 mars 2015 à 17:53
0
Merci
Bonsoir Yannick,

si je crois comprendre ce que tu veux faire, tu esseayes d'avoir la PB affichée avec value.max = -1 au final mais dans le commentaire du code, tu as dit "ma progress bar ne s'affichera complete qu'a la fin du traitement chronophage" ! c'est normal parce que tu as mis (Pb.Visible = True) en dernier !

je ne sais pas si c'est ça ton problème mais j'aimerais bien t'aider si tu éclaires ma lanterne !
yayou49 7 Messages postés lundi 17 février 2014Date d'inscription 30 mars 2015 Dernière intervention - 19 mars 2015 à 18:05
Bonsoir Guatto,

ce n'est pas value.max = -1 mais pb.value = max-1
dans l'exemple c'est 5000-1 donc 4999
(j'aurai pu écrire pb.value = pb.maximum - 1, ce qui revenait au même)

En ce qui concerne le pb.visible = true, même si je le met au début du paramétrage de la PB, cela ne change rien.

C'est l'ensemble du code qui se trouve après "if start = true" qui ne s'exécute (malheureusement) qu'à la fin du traitement chronophage et non pas avant.

Quand je click sur le BtGo, il devrait d'abord initialiser la PB et la rendre visible puis ensuite exécuter le traitement chronophage puis rendre la PB non visible.
Commenter la réponse de guatto
cs_Le Pivert 5454 Messages postés jeudi 13 septembre 2007Date d'inscriptionContributeurStatut 20 octobre 2018 Dernière intervention - 19 mars 2015 à 18:42
0
Merci
Bonjour,

Avec un BackgroundWorker, voici le code:


Imports System.ComponentModel' je ne me rappelle pas si c'est nécessaire
#Region "Thread"
 Private Sub BtGo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdcreer.Click
        BackgroundWorker1.RunWorkerAsync()
    End Sub
 Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim MyThread As BackgroundWorker = CType(sender, BackgroundWorker) 'récupération du thread d'arrière plan
        Dim pourcent As Integer
        MyThread.ReportProgress(pourcent) 'pourcent est un Integer indiquant l'état d'avancement.
        'mettre l'action a effectuer
    End Sub
    Private Sub BackgroundWorker1_ProgressChanged( _
ByVal sender As Object, _
ByVal e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged

        ProgressBar1.Value = e.ProgressPercentage
        ProgressBar1.Style = ProgressBarStyle.Marquee
    End Sub
    'Quand le code d'arrière plan est terminé la procédure RunWorkerCompleted est exécutée.
    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, _
     ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted

        ProgressBar1.Style = ProgressBarStyle.Blocks
        ProgressBar1.Value = 100
        ' ici, elle affiche un message indiquant que le thread d'arrière plan est terminé.  
        MessageBox.Show("Opération réussie ", "Action a effectuer", MessageBoxButtons.OK, MessageBoxIcon.Information)
        cmdsave.Enabled = True
        cmdcreer.Enabled = False
    End Sub

yayou49 7 Messages postés lundi 17 février 2014Date d'inscription 30 mars 2015 Dernière intervention - 19 mars 2015 à 22:56
merci le pivert pour cette réponse.
J'essaye le code dés lundi et je ferai un feedback.
yayou49 7 Messages postés lundi 17 février 2014Date d'inscription 30 mars 2015 Dernière intervention - 20 mars 2015 à 19:09
Je n'est pas encore eu le temps de tester le code, mais en le lisant je comprend bien le mode de fonctionnement et je pense que dans ce cas cela fonctionne.

Ceci étant dit, j'aurai une petite variante de mon probleme à soumettre car je ne pense pas que dans ce cas, cette solution fonctionne.

Donc, on prend la form1 comme décrit, mais on supprime le BtGo de la form et du code.
On créé une form2 qui inherite de la form1.
Dans cette form2, on met le bouton BtGo avec le même code que celui qui était dans la form1.

Cela donne pour la form1::
Public Class Form1

Private Sub Barre(ByVal Start As Boolean)

If Start = True Then

'*** Paramétrage de la Progress Bar ***
Pb.Minimum = 0
Pb.Maximum = 5000
Pb.Value = 4999 'Valeur maximum - 1
Dim Pos As New System.Drawing.Point
Pos.X = 0
Pos.Y = 10
Pb.Location = Pos
'on defini la largeur de la barre, égale à la largeur de la form.
Pb.Width = Me.Width
Pb.Visible = True 'parce que la progress bar est visible(false) dans la form


'et c'est là que je ne sais plus quoi faire car ma progress bar ne s'affichera complete qu'a la fin du traitement chronophage............

Else
Pb.Visible = False
End If

End Sub

End Class


et pour la form2:

Public Class Form2
inherit form1

Private Sub BtGo_Click(sender As System.Object, e As System.EventArgs) Handles BtGo.Click

'Appel du démarrage de la progress bar (parametre = True)
Barre(True)


'// appel à la sub de traitement chronophage
'//
'//

'Appel de l'arret de la progress bar (parametre = False)
Barre(False)

End Sub

End Class


L'objectif est de ne pas modifier le code qui se trouve dans le BtGo et de gérer l'affichage de cette fameuse progress Bar.

J'espere avoir une réponse aussi efficace que la premiere ^^ ;)

Merci.
Commenter la réponse de cs_Le Pivert
cs_Le Pivert 5454 Messages postés jeudi 13 septembre 2007Date d'inscriptionContributeurStatut 20 octobre 2018 Dernière intervention - 21 mars 2015 à 08:26
0
Merci
Cela ne peut pas fonctionner pour 2 raisons:

1)Tu ne peux pas appeler Private Sub Barre(ByVal Start As Boolean) tel qu'il est d'un autre Form que celui dans lequel il a été écrit.

2)Pour que la ProgressBar fonctionne en même temps que l'action qui s'effectue, il faut un thread d'arrière plan. C'est pour cela que l'on utilise unBackgroundWorker

Commenter la réponse de cs_Le Pivert
yayou49 7 Messages postés lundi 17 février 2014Date d'inscription 30 mars 2015 Dernière intervention - 30 mars 2015 à 11:39
0
Merci
pour ceux que ça intéresse, voici le code qui permet de faire ce que j'ai demandé:

Form1:

Imports System.Threading

Public Class Form1

Private mThread As Thread
Public Sub DemarrerTraitement(tache As action)
mThread = New Thread(New ThreadStart(Sub()
Me.Invoke(Sub(ctrl As Form1) DebutTraitement(ctrl), New Object() {Me})
tache.Invoke()
Me.Invoke(Sub(ctrl As Form1) FinTraitement(ctrl), New Object() {Me})
End Sub
))
mThread.Start()

End Sub


Private Sub DebutTraitement(window As Form1)
window.Barre(True)
End Sub

Private Sub FinTraitement(window As Form1)
window.Barre(False)
End Sub


Public Sub Barre(ByVal Start As Boolean)

If Start = True Then

'*** Paramétrage de la Progress Bar ***
Pb.Minimum = 0
Pb.Maximum = 5000
Pb.Value = 4999 'Valeur maximum - 1
Dim Pos As New System.Drawing.Point
Pos.X = 0
Pos.Y = 10
Pb.Location = Pos
'on defini la largeur de la barre, égale à la largeur de la form.
Pb.Width = Me.Width
Pb.Visible = True 'parce que la progress bar est visible(false) dans la form1

Else
Pb.Visible = False
End If

End Sub


End Class


et Form2:

Imports System.Threading
Public Class Form2
Inherits Form1

Private Sub BtGo_Click(sender As System.Object, e As System.EventArgs) Handles BtGo.Click



DemarrerTraitement(New Action(Sub()

'appel au traitement long
'.......
For i = 1 To 100
Thread.Sleep(100)
Next
'.......

End Sub))


End Sub

End Class


Merci beaucoup à Vincent.
Commenter la réponse de yayou49

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.