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

Picsonald Messages postés 23 Date d'inscription lundi 30 décembre 2002 Statut Membre Dernière intervention 7 novembre 2020 - 2 mars 2010 à 18:00
Picsonald Messages postés 23 Date d'inscription lundi 30 décembre 2002 Statut Membre Dernière intervention 7 novembre 2020 - 15 mars 2010 à 09:58
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 !

8 réponses

krimog Messages postés 1860 Date d'inscription lundi 28 novembre 2005 Statut Membre Dernière intervention 14 février 2015 50
3 mars 2010 à 09:50
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é. -
0
BunoCS Messages postés 15330 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 25 novembre 2022 103
3 mars 2010 à 10:33
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...
0
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 42
3 mars 2010 à 11:31
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+.
0
Picsonald Messages postés 23 Date d'inscription lundi 30 décembre 2002 Statut Membre Dernière intervention 7 novembre 2020
3 mars 2010 à 11:47
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 !
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
krimog Messages postés 1860 Date d'inscription lundi 28 novembre 2005 Statut Membre Dernière intervention 14 février 2015 50
3 mars 2010 à 12:05
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é. -
0
Picsonald Messages postés 23 Date d'inscription lundi 30 décembre 2002 Statut Membre Dernière intervention 7 novembre 2020
3 mars 2010 à 14:25
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 ?
0
cs_lulu42 Messages postés 10 Date d'inscription jeudi 25 mars 2004 Statut Membre Dernière intervention 4 mars 2010
4 mars 2010 à 11:51
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.

++
0
Picsonald Messages postés 23 Date d'inscription lundi 30 décembre 2002 Statut Membre Dernière intervention 7 novembre 2020
15 mars 2010 à 09:58
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 !
0