Contrôle lourd : nombreux redimentionnement. Comment l'optimiser ?

Signaler
Messages postés
23
Date d'inscription
lundi 30 décembre 2002
Statut
Membre
Dernière intervention
7 novembre 2020
-
Messages postés
23
Date d'inscription
lundi 30 décembre 2002
Statut
Membre
Dernière intervention
7 novembre 2020
-
Salut à tous,

Je suis actuellement en train de développer un UserControl (WinForm) de planning (un peu façon « Calendrier Outlook », mais avec le temps en abscisses). Pour ce faire j'imbrique de nombreux Panel et PictureBox les uns dans les autres, et j'affiche dans certains d'eux des images PNG à couleurs transparentes.



Lorsque je clique sur un groupe, la liste des évènements apparait. lorsque je reclique, elle disparait.

Ceci m'oblige a décaler verticalement tous les composants situés en dessous du groupe sur lequel je clique. Or, si mon planning est chargé, ceci le fait « scintiller ». En plein écran, par exemple, avec 20 groupes : lorsque je clique sur le « Groupe 1 », les événement apparaissent, puis le planning ce met à « clignoter » pendant 4-5 (vraies)
secondes (comme si des bandes blanches passaient au dessus de lui de haut en bas)...

Auriez-vous une idée d'où ça vient ?


Je pense que le rafraichissement des contrôles est en cause. Aussi sachez que passer la propriété « DoubleBuffered » à « True » n'a donné que peu de résultats. De même, l'utilisation des méthodes « SuspendLayout() » et « ResumeLayout() » change peu de choses. En revanche, il n'y a plus de problème si je rend mon contrôle « Visible false » au début de la méthode qui s'occupe du redimensionnement, et si je le remet « Visible true » après : lorsque je clique sur le « Groupe 1 », le planning disparait 1/10 de seconde, puis revient tout beau tout propre :-). Parfait... mais crade...


D'avance, merci pour vos réponses :) Bonne soirée !
A voir également:

8 réponses

Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
42
Salut

Je ne connais pas bien les picturebox, mais tu peux toujours faire un buffer toi-même.
En gros, au lieu de dessiner sur l'image de ta picturebox, tu dessines sur une autre image en mémoire, et une fois le tout dessiné, tu remplaces l'image de ta picturebox par celle que tu viens de faire.

Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -
Messages postés
14884
Date d'inscription
lundi 11 juillet 2005
Statut
Modérateur
Dernière intervention
30 novembre 2020
93
Hello,
Es-tu obligé d'utiliser des png? Un simple dégradé de couleur semble être suffisant dans ton cas.


@+
Buno
----------------------------------------
L'urgent est fait, l'impossible est en cours. Pour les miracles, prévoir un délai...
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
34
Salut, je partage les deux idées précédentes.. de plus tu ne devrais pas imbriquer des tas de Panels et de PictureBox mais dessiner tout ça avec GDI+.
Messages postés
23
Date d'inscription
lundi 30 décembre 2002
Statut
Membre
Dernière intervention
7 novembre 2020

Hey !

Merci pour vos réponses !

Je viens d'appliquer votre idée de générer moi même l'image de dégradé pour chacun des groupes.

Voici l'extrait de code (événement « Paint ») :

private Rectangle _rectangleDégradéPnlContenuGroupe =   new Rectangle(0, 0, 3840, 28);
private LinearGradientBrush _dégradéPnlContenuGroupe;

public SpécialPlanning() // Constructeur (volontairement abrégé)
{
     _dégradéPnlContenuGroupe = new LinearGradientBrush(_rectangleDégradéPnlContenuGroupe,
          Color.FromArgb(48, Color.DimGray), Color.Transparent, LinearGradientMode.Vertical);
}

private void PnlContenuGroupe_Paint(object sender, PaintEventArgs e)
{
     e.Graphics.FillRectangle(_dégradéPnlContenuGroupe, _rectangleDégradéPnlContenuGroupe);
     e.Graphics.DrawLine(new Pen(Color.White), 0, 0, 3840, 0);
     e.Graphics.DrawLine(new Pen(Color.DarkGray), 0, 1, 3840, 1);
}


Votre idée implique un bon gain de performance (de l'ordre de 2 secondes soit 40% de gain) ! Ça marche plutôt bien (et je suis sur que coté mémoire c'est meilleur également) !
Malheureusement, lorsque je clique sur le « Groupe 1 », le planning ce met à « clignoter » pendant encore 2-3 secondes avec les méthodes « SuspendLayout() » et « ResumeLayout() », tandis que si je laisse les « Visible <gras>false » et les « Visible true »</gras> à la place : 1/10 de seconde...

En tout cas, je garde votre idée. Si vous en avez d'autres, je suis tout ouïe !
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
42
Tu as essayé ma méthode pour éviter le clignotement ?

Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -
Messages postés
23
Date d'inscription
lundi 30 décembre 2002
Statut
Membre
Dernière intervention
7 novembre 2020

Je pensais que tu me disais la même chose que Bruno, mais à priori non...

En fait, mon planning est une succession de Panel et de PictureBox imbriqués (ces deux contrôles sont très comparables) :
La grille des heures est un Panel (son image de fond est une image PNG étirée (Stretch)).
À l'intérieur, on trouve plusieurs panels dit « PnlContenuGroupe » : leur image de fond est un dégradé générée par le code que j'ai posté ci-dessus.
À l'intérieur de chaque « PnlContenuGroupe » on trouve des « PnlRendezVous » qui contiennent chacun trois PicturesBox (l'arrondi de gauche, la partie centrale (étirée) et l'arrondi de droite). Sur le Screenshot on peut voir 5 « PnlRendezVous ».

C'est pourquoi j'ai du mal à voir comment je pourrais tout calculer en mémoire plutôt que d'afficher directement les éléments... Je pensais que « SuspendLayout() » servait à neutraliser l'affichage (et laisser le planning ce générer en mémoire) mais non : ça ne fait pas ça...

Peux-tu m'éclaircir sur ton idée s'il te plait ?
Messages postés
10
Date d'inscription
jeudi 25 mars 2004
Statut
Membre
Dernière intervention
4 mars 2010

Salut ^^

Je penses personnellement que tu devrais te concentrer sur le dessin GDI+. J'ai perso fait ça en Java, mais aucune idée de comment ça marche chez Microsoft.

L'idéal serait un système de verrouillage de rafraîchissement, que pour certains événements afin de fluidifier l'affichage.

++
Messages postés
23
Date d'inscription
lundi 30 décembre 2002
Statut
Membre
Dernière intervention
7 novembre 2020

Yep, merci pour ta réponse, cela dit il semble que passer la propriété « Visible » à False verrouille le rafraichissement mieux qu'un appel à la méthode « SuspendLayout() ».

C'est ça qui m'étonne. C'est un peu crade mais je vais faire avec je crois ^^

Merci à tous pour l'aide apportée !