comment arrêter le scintillement C#, winforms
J'ai un programme qui est essentiellement comme une application de la peinture. Cependant, mon programme a un scintillement questions. J'ai la ligne suivante dans mon code (qui doit se débarrasser de scintillement - mais qui ne marche pas):
this.SetStyle(ControlStyles.AllPaintingInWmPaint
| ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);
mon code(sans les super et les sous-catégories pour les formes est comme suit:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Paint
{
public partial class Paint : Form
{
private Point startPoint;
private Point endPoint;
private Rectangle rect = new Rectangle();
private Int32 brushThickness = 0;
private Boolean drawSPaint = false;
private List<Shapes> listOfShapes = new List<Shapes>();
private Color currentColor;
private Color currentBoarderColor;
private Boolean IsShapeRectangle = false;
private Boolean IsShapeCircle = false;
private Boolean IsShapeLine = false;
public SPaint()
{
InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);
currentColor = Color.Red;
currentBoarderColor = Color.DodgerBlue;
IsShapeRectangle = true;
}
private void panelArea_Paint(object sender, PaintEventArgs e)
{
Graphics g = panelArea.CreateGraphics();
if (drawSPaint == true)
{
Pen p = new Pen(Color.Blue);
p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
if (IsShapeRectangle == true)
{
g.DrawRectangle(p, rect);
}
else if (IsShapeCircle == true)
{
g.DrawEllipse(p, rect);
}
else if (IsShapeLine == true)
{
g.DrawLine(p, startPoint, endPoint);
}
}
foreach (Shapes shape in listOfShapes)
{
shape.Draw(g);
}
}
private void panelArea_MouseDown(object sender, MouseEventArgs e)
{
startPoint.X = e.X;
startPoint.Y = e.Y;
drawSPaint = true;
}
private void panelArea_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
if (e.X > startPoint.X)
{
rect.X = startPoint.X;
rect.Width = e.X - startPoint.X;
}
else
{
rect.X = e.X;
rect.Width = startPoint.X - e.X;
}
if (e.Y > startPoint.Y)
{
rect.Y = startPoint.Y;
rect.Height = e.Y - startPoint.Y;
}
else
{
rect.Y = e.Y;
rect.Height = startPoint.Y - e.Y;
}
panelArea.Invalidate();
}
}
private void panelArea_MouseUp(object sender, MouseEventArgs e)
{
endPoint.X = e.X;
endPoint.Y = e.Y;
drawSPaint = false;
if (rect.Width > 0 && rect.Height > 0)
{
if (IsShapeRectangle == true)
{
listOfShapes.Add(new TheRectangles(rect, currentColor, currentBoarderColor, brushThickness));
}
else if (IsShapeCircle == true)
{
listOfShapes.Add(new TheCircles(rect, currentColor, currentBoarderColor, brushThickness));
}
else if (IsShapeLine == true)
{
listOfShapes.Add(new TheLines(startPoint, endPoint, currentColor, currentBoarderColor, brushThickness));
}
panelArea.Invalidate();
}
}
private void rectangleToolStripMenuItem_Click(object sender, EventArgs e)
{
IsShapeRectangle = true;
IsShapeCircle = false;
IsShapeLine = false;
}
private void ellipseToolStripMenuItem_Click(object sender, EventArgs e)
{
IsShapeRectangle = false;
IsShapeCircle = true;
IsShapeLine = false;
}
private void lineToolStripMenuItem_Click(object sender, EventArgs e)
{
IsShapeCircle = false;
IsShapeRectangle = false;
IsShapeLine = true;
}
private void ThicknessLevel0_Click(object sender, EventArgs e)
{
brushThickness = 0;
}
private void ThicknessLevel2_Click(object sender, EventArgs e)
{
brushThickness = 2;
}
private void ThicknessLevel4_Click(object sender, EventArgs e)
{
brushThickness = 4;
}
private void ThicknessLevel6_Click(object sender, EventArgs e)
{
brushThickness = 6;
}
private void ThicknessLevel8_Click(object sender, EventArgs e)
{
brushThickness = 8;
}
private void ThicknessLevel10_Click(object sender, EventArgs e)
{
brushThickness = 10;
}
private void ThicknessLevel12_Click(object sender, EventArgs e)
{
brushThickness = 12;
}
private void ThicknessLevel14_Click(object sender, EventArgs e)
{
brushThickness = 14;
}
private void FillColour_Click(object sender, EventArgs e)
{
ColorDialog fillColourDialog = new ColorDialog();
fillColourDialog.ShowDialog();
currentColor = fillColourDialog.Color;
panelArea.Invalidate();
}
private void button1_Click(object sender, EventArgs e)
{
ColorDialog fillColourDialog = new ColorDialog();
fillColourDialog.ShowDialog();
currentBoarderColor = fillColourDialog.Color;
panelArea.Invalidate();
}
}
}
Comment puis-je arrêter le clignotement?
*Mise à JOUR:*Ce code fonctionne très bien quand je dessine directement sur le formulaire. Cependant, lorsque j'essaie de tirer sur le panneau, le clignotement devient un problème
- Avez-vous également définir
this.DoubleBuffered = true;
? - Marc Gravel, j'ai juste essayé d'ajouter dans cet.DoubleBuffered = vrai; et c'est encore vacillante comme un fou :S
- Est panelArea plein de contrôles? Invalider fonctionne de manière récursive et, par conséquent, peut-coup de pied de chaque contrôle enfant dans panelArea à repeindre
- Régime non, panelArea est juste un panneau que j'utilise pour dessiner. Il n'a pas de commandes mais..
- Avez-vous mis la ClipSiblings style sur toutes vos commandes? Il est possible que le scintillement est causé par de multiples repeint sur les commandes (si ils se chevauchent).
- Osterman Hmm, je viens de déménager tout donc rien ne se chevauchent dans le moindre. Il y a encore beaucoup de scintillement passe bien :S
- +1, franchement le SetStyle fonction m'a aidé à effacer le scintillement. c# est soooo beaucoup plus mieux que le c++ !!!
Vous devez vous connecter pour publier un commentaire.
Pour une "solution plus propre" et de les maintenir à l'aide de la plaque de base, vous pouvez simplement utiliser la Réflexion pour mettre en œuvre la double mise en mémoire tampon, en ajoutant ce code dans le formulaire qui contient les panneaux dans lesquels vous voulez attirer dans
Où "DrawingPanel" est le nom du groupe que vous voulez faire le double buffering.
Je sais que beaucoup de temps s'est écoulé depuis que la question a été posée, mais cela peut aider quelqu'un dans le futur.
Enfin résolu le scintillement. Depuis que j'ai dessiné sur un panneau au lieu de la forme de la ligne de code ci-dessous ne va pas résoudre le scintillement:
SetStyle doit être de type 'Votreprojet.Votreprojet " (ou dérivés), par conséquent, vous devez créer une classe en tant que telle (de sorte que vous pouvez utiliser MyPanel qui seront tirés de l'SPaint.SPaint et, par conséquent, vous permettant d'utiliser le doublebuffering directement pour le panneau - plutôt que de la forme):
Après vous avez fait cela(bien que vous devriez vraiment ne jamais modifier le code du designer à moins que vous vraiment savoir ce que vous faites), vous devrez modifier le Formulaire.Le concepteur.cs. À l'intérieur de ce fichier, vous trouverez un code qui ressemble à ceci:
La ligne ci-dessus doit être modifié pour:
Après que j'ai terminé ces étapes, mon programme de peinture n'est plus saccadée.
Pour toute autre personne ayant le même problème, le problème est enfin résolu.
Profitez-en!
Copiez et collez ceci dans votre projet
Cela permet un double tampon pour toutes les commandes de la forme, le niveau vers le bas, sinon double mise en mémoire tampon doit être individuellement activé pour chacun... vous pouvez affiner double bufferring après parce recouvert double mise en mémoire tampon peut donner des effets secondaires indésirables.
J'ai eu le même problème. Je n'arrivais jamais à 100% pour me débarrasser du flicker (voir point 2), mais j'ai utilisé ce
ainsi que
Le principal problème de scintillement est de s'assurer que vous
winforms appelle la
OnPaint
méthode à chaque fois que le formulaire doit être redessiné. Il y a beaucoup de façons, il peut être devalidated, y compris le déplacement d'un curseur de la souris sur la forme peut parfois invoquer un événement de redessin.Et remarque importante à propos de
OnPaint
, est de ne pas commencer à partir de zéro à chaque fois, vous, au lieu de démarrer à partir de l'endroit où vous étiez, si vous inondation remplir de la couleur d'arrière-plan, vous êtes susceptible d'obtenir le scintillement.Enfin votre gfx objet. À l'intérieur de
OnPaint
vous devrez recréer l'objet graphique, mais SEULEMENT si la taille de l'écran a changé. recréer l'objet est très cher, et il doit être éliminé avant qu'il soit recréé (collecte des ordures n'est pas à 100% les manipuler correctement, ou le dit de la documentation). J'ai créé une variable de classeet ensuite utilisé localement dans
OnPaint
comme ça, mais c'était parce que j'avais besoin d'utiliser le gfx objet dans d'autres endroits dans ma classe. Sinon, NE PAS le FAIRE. Si vous êtes seulement la peinture dans OnPaint, alors s'il vous plaît utilisere.Graphics
!!Espère que cette aide.
protected override void OnPaint(PaintEventArgs e) {}
Le nouvel objet s'affichera dans votre liste d'éléments à déposer dans votre formulaire. Aussi, vous pouvez éditer le code pour changer le type de référence, si vous avez déjà le groupe d'experts créé et n'ont pas l'option facile de simplement de le recréer.Double mise en mémoire tampon ne va pas être de beaucoup d'aide ici, j'ai peur. Je suis tombé sur ça il y a longtemps et finit par l'ajout d'un panneau séparé plutôt maladroit, mais cela a fonctionné pour mon application.
Faire le groupe spécial initial que vous avez ( panelArea ) une zone transparente, et de le mettre sur le dessus d'un 2ème panneau, ce que vous appelez panelDraw par exemple. Assurez-vous d'avoir panelArea en face. Je fouettée et il s'est débarrassé de le scintillement, mais la forme qui est en cours d'élaboration étalés il n'est donc pas une solution complète soit.
Un panneau transparent peut être fait en remplaçant la peinture des actions à partir du panneau d'origine:
L'idée est de gérer le dessin de la temporaire de forme au cours de l'événement MouseMove de l' 'panelArea" et repeindre le "panelDraw" sur l'Événement MouseUp.
Je sais que c'est vraiment une vieille question, mais peut-être que quelqu'un va trouver utile.
Je voudrais faire peu d'amélioration à la vipère de réponse.
Vous pouvez faire simple extension de Panneau de la classe et le paramètre de masquage de la propriété par le biais de la réflexion.
Si votre Panneau de la variable nom est myPanel vous pouvez les appeler
myPanel.SetDoubleBuffered();
et c'est tout. Le Code est beaucoup plus propre.
Je conseille primordial OnPaintBackground et de la manipulation de l'arrière-plan effacer vous-même. Si vous savez que vous faites de la peinture sur le contrôle de l'ensemble, vous pouvez tout simplement ne rien faire dans OnPaintBackground (n'appelez pas la méthode de base) et il empêchera la couleur de fond peintes en premier
Dans cette condition, vous devez activer le double de la mémoire tampon .
Ouvrir le formulaire et accédez aux propriétés du formulaire et de les appliquer à double tampon true;
ou vous pouvez également écrire ce code .
En forme de chargement.
voici le programme de déplacement de cercle .net, qui ne clignote pas.
si tous les ci-dessus ne fonctionne pas, vous pouvez toujours créer votre propre tampon double
lien vers les directives de Microsoft tutoriel: https://docs.microsoft.com/en-us/dotnet/framework/winforms/advanced/how-to-reduce-graphics-flicker-with-double-buffering-for-forms-and-controls
espère que cela fonctionne pour vous
Si la mémoire est serré (si vous ne voulez pas la mémoire des coûts de double-buffering), une façon possible de RÉDUIRE, mais pas éliminer le scintillement est de fixer la couleur de fond la couleur dominante dans votre scène.
Pourquoi cette aide: le scintillement momentané flash de la couleur d'arrière-plan, dont les OS tire avant de tirer des contrôles enfants ou votre code de dessin personnalisé. Si flash est une couleur qui est plus proche de la couleur finale pour être affiché, il sera moins perceptible.
Si vous n'êtes pas sûr de quelle couleur pour commencer, commencer avec 50% de gris, parce que c'est un moyen de noir et de blanc, afin de se rapprocher de la plupart des couleurs dans votre scène.
Essayez d'insérer le dessin de la logique dans la forme actuelle du
méthode. Dans ce cas, vous devez utiliser le paramètre e pour obtenir de l'objet Graphique. L'utilisation de e.Les graphiques de la propriété. Ensuite, vous devez invoquer la méthode Invalidate() pour ce formulaire à chaque fois que le formulaire doit être redessiné.
PS: DoubleBuffered doit être définie sur true.
il suffit de ne
this.Refresh()
quand montre la forme.Pouvez-vous essayer à l'aide d'une minuterie et d'booléen pour vérifier si la souris est en bas, et de la peinture à cet endroit, à l'aide d'une variable de nouveau vérifier si l'utilisateur a déplacé sa souris, si déplacé de la peinture qui tache trop etc.
Ou simplement vérifier si la souris vers le bas(via booléenne qui détermine vrai lorsque la souris est en bas) à l'aide d'une minuterie et de le peindre en considérant que vous êtes probablement en train de dessiner un pixel, pas comme vous de l'ombre etc. Au lieu d'utiliser réelle mousedown. Ainsi, vous vérifiez toutes les 1 seconde au lieu de 0,0001 et il l'habitude de scintillement. Ou vice-versa, à essayer avec votre propre temps.