wie man aufhört zu flackern C # winforms
Ich habe ein Programm, das im wesentlichen wie ein paint-Anwendung. Allerdings, mein Programm hat einige flackernde Probleme. Ich habe folgende Zeile in meinem code (der sollte die Beseitigung von flackern - funktioniert aber nicht):
this.SetStyle(ControlStyles.AllPaintingInWmPaint
| ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);
mein code(ohne den super-und sub-Klassen für die Formen ist wie folgt:
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();
}
}
}
Wie verhindere ich das flackern?
*UPDATE:*Dieser code funktioniert eigentlich Super, wenn ich die Zeichnung direkt auf die form. Jedoch, wenn ich versuche zu zeichnen, auf dem panel, das flackern ein Problem wird
Kommentar zu dem Problem
Haben Sie auch
.DoubleBuffered = true;
? @ Marc Gravell ich habe gerade versucht, indem in diesem.DoubleBuffered = true; und es ist immer noch flackern wie verrückt :S
Ist panelArea voller steuert? Ungültig rekursiv arbeitet und daher könnte kick jedes untergeordnete Steuerelement in panelArea selbst aktualisieren
@ Gemeinwesen, Nein, panelArea ist nur ein panel verwende ich zum zeichnen auf. Es hat keine Steuerelemente, wenn..
Haben Sie die ClipSiblings Stil auf alle Steuerelemente? Es ist möglich, das flackern verursacht wird, die durch mehrere repaints auf die Steuerelemente (wenn Sie sich überlappen).
InformationsquelleAutor der Frage BigBug | 2011-11-08
Du musst angemeldet sein, um einen Kommentar abzugeben.
Schließlich löste das flimmern. Da ich zeichne auf einem panel statt der form die code-Zeile unten keine Lösung für das flackern:
SetStyle muss vom Typ 'YourProject.YourProject " (oder davon abgeleitet) daher müssen Sie eine Klasse erstellen, die als solche (so dass Sie verwenden können, MyPanel, die abgeleitet werden von SPaint.SPaint und daher ermöglicht die Verwendung doublebuffering direkt für das panel - eher als die form):
Nachdem Sie dies getan haben(obwohl Sie sollten wirklich nie Bearbeiten der designer-code, es sei denn, Sie wirklich wissen, was Sie tun) müssen Sie Bearbeiten Sie die Form.Designer.cs. In dieser Datei finden Sie code, der wie folgt aussieht:
Die obige Zeile muss geändert werden:
Nachdem ich diese Schritte durchgeführt, mein paint Programm nicht mehr flackert.
Für jemand anderen mit dem gleichen Problem, das problem ist endlich gelöst.
Genießen!
InformationsquelleAutor der Antwort BigBug
Für eine "sauberere Lösung" und in Ordnung zu halten mit der base-Bedienfeld können Sie einfach mithilfe von Reflektion zur Umsetzung der doppelten Pufferung, indem Sie diesen code an das Formular hält, dass die Gremien, in denen Sie zeichnen möchten, in
Wo "DrawingPanel" ist der name der Platte, die Sie wollen, um die doppelte Pufferung.
Ich weiß, ziemlich viel Zeit ist vergangen, seit die Frage gestellt wurde, aber dies könnte helfen, jemand in der Zukunft.
InformationsquelleAutor der Antwort viper
Kopieren und fügen Sie diesen in Ihr Projekt
Dies ermöglicht eine Doppelpufferung für alle Steuerelemente aus der Formular-Ebene nach unten, sonst doppelte Pufferung benötigt werden individuell aktiviert, die für jeden... möchten Sie vielleicht, um die Feinabstimmung Doppel-bufferring nach diesem, da schirmte Doppel-Pufferung geben kann unerwünschte Nebenwirkungen.
InformationsquelleAutor der Antwort user3641393
Habe ich das gleiche problem hatte. Ich war nie in der Lage zu 100% befreie mich von dem flimmern (siehe Punkt 2), aber ich habe dieses
sowie
Die wichtigste Frage für die flimmernde macht sicher, dass Sie
winforms ruft die
OnPaint
Methode jedes mal die form neu gezeichnet werden muss. Es gibt viele Möglichkeiten, es kann sein, devalidated, einschließlich bewegen des Mauszeigers über das Formular können manchmal rufen Sie ein redraw-event.Und wichtiger Hinweis über
OnPaint
, ist Sie nicht von vorne anfangen jedes mal, wenn Sie stattdessen beginnen, wo Sie waren, wenn Sie füllt die Hintergrundfarbe, sind Sie wahrscheinlich gehen, um flackern.Schließlich Ihre gfx-Objekt. Innerhalb
OnPaint
Sie müssen wieder das graphics-Objekt, aber NUR, wenn die Bildschirmgröße geändert wurde. die Wiederherstellung des Objekts ist sehr teuer, und es muss entsorgt werden, bevor Sie neu erstellt wird (garbage collection nicht 100% behandeln es richtig oder so sagt-Dokumentation). Ich erstellte eine Klasse variable, und dann verwendet es lokal in
OnPaint
wie so, aber das war, weil ich brauchte, um das gfx-Objekt in anderen Orten in meiner Klasse. Ansonsten TUN Sie DAS NICHT. Wenn Sie nur die Malerei, in OnPaint, dann nutzen Sie bittee.Graphics
!!Hoffe, das hilft.
InformationsquelleAutor der Antwort ohmusama
Doppelte Pufferung ist nicht viel Hilfe hier, fürchte ich. Ich lief in diese eine Weile her und endete hinzufügen einer separaten Bedienfeld auf eine etwas ungeschickte Art und Weise, aber es funktionierte für meine Anwendung.
Dass das original-panel, die Sie haben ( panelArea ) einen transparenten Bereich, und legen Sie es auf der Oberseite ein 2. panel, die Sie nennen, panelDraw zum Beispiel. Stellen Sie sicher, dass panelArea vor. Ich peitschte diese bis und er entledigte sich das flackern, ließ aber die Form, die abgezogen wurde beschmiert, so dass es keine vollständige Lösung.
Einem transparenten panel gemacht werden können, durch zwingende Farbe Aktionen von der original-Platte:
Die Idee ist, zu behandeln Zeichnung der temporären Form während des MouseMove-Ereignisses der 'panelArea' und NUR repaint 'panelDraw' auf das MouseUp-Ereignis.
InformationsquelleAutor der Antwort Tom
Ich würde empfehlen überschreiben OnPaintBackground und Handhabung der hintergrund löschen sich selbst. Wenn Sie wissen, dass Sie die Malerei die ganze Steuerung kann man eben nichts machen in OnPaintBackground (rufen Sie nicht die Basis-Methode) und es wird verhindert, dass die hintergrund-Farbe bemalt werden erste
InformationsquelleAutor der Antwort Matt
Ich weiß, das ist wirklich eine alte Frage, aber vielleicht wird jemand es nützlich finden.
Ich möchte kleine Verbesserung zu viper ' s Antwort.
Können Sie machen eine einfache Erweiterung, die Panel-Klasse und die Einstellung ausblenden-Eigenschaft durch Reflexion.
Wenn Ihr Panel-variable ist der name myPanel Sie können einfach anrufen
myPanel.SetDoubleBuffered();
und das ist es. Code sieht viel sauberer.
InformationsquelleAutor der Antwort thorgil
In diesem Zustand haben Sie zum aktivieren der Doppel-Puffer .
Öffnen Sie aktuelle Formular und gehen zu Formular-Eigenschaften und doppelten Puffer true;
oder Sie können auch dieser code zu schreiben .
In Formular laden.
InformationsquelleAutor der Antwort
hier ist das Programm der bewegten Kreis .net, dass nicht flackert.
InformationsquelleAutor der Antwort sanjay
Wenn der Speicher knapp ist (so dass Sie nicht wollen, dass die Speicher Kosten von double-buffering), eine Möglichkeit zu REDUZIEREN, wenn nicht beseitigen, flimmern, ist das festlegen der hintergrund-Farbe, um die dominierende Farbe in Ihrem aktuellen Szene.
Warum das hilft: flimmern ist einem momentanen Blitz der hintergrund-Farbe, die das OS zieht vor Zeichnung untergeordneten Steuerelemente oder Ihr benutzerdefiniertes zeichnen-code. Wenn das flash ist eine Farbe, die näher an der Farbe angezeigt werden, es werden weniger bemerkbar.
Wenn Sie nicht sicher sind, welche Farbe, mit zu beginnen, starten Sie mit 50% Grau ist, denn dies ist ein Durchschnitt von schwarz und weiß, so wird näher auf die wichtigsten Farben in Ihrer Szene.
InformationsquelleAutor der Antwort ToolmakerSteve
Setzen Sie eine Zeichnung, die Logik in der aktuellen form ist
Methode. In diesem Fall sollten Sie den parameter e zu bekommen Graphics-Objekt. Verwenden Sie e.Graphics-Eigenschaft. Dann sollten Sie aufrufen von Invalidate () - Methode für diese form, wenn die form neu gezeichnet werden muss.
PS: DoubleBuffered auf true gesetzt werden muss.
InformationsquelleAutor der Antwort DeeDee
wenn alle der oben genannten nicht funktioniert, können Sie immer erstellen Sie Ihre eigenen double buffer
link zu Microsofts tutorial: https://docs.microsoft.com/en-us/dotnet/framework/winforms/advanced/how-to-reduce-graphics-flicker-with-double-buffering-for-forms-and-controls
hofft, dass er für Sie arbeitet
InformationsquelleAutor der Antwort Jan Tamis Kossen
Können Sie versuchen, mit einem timer und boolean zu prüfen, ob Maustaste gedrückt ist, und die Farbe an dieser Stelle, dass die Verwendung einer Variablen überprüfen Sie, ob Benutzer bewegt seine Maus bewegt, Lackierung, spot-zu etc.
Oder einfach nur überprüfen, wenn die Maus nach unten(mittels boolescher Wert, der true setzt, wenn die Maustaste gedrückt ist) über einen timer und malen Sie erwägen, versuchen Sie wahrscheinlich nur Farbe ein pixel, nicht wie Sie Schatten etc. Statt mit tatsächlichen mousedown. So überprüfen Sie alle 1 Sekunde statt 0,0001 und es nicht flimmern. Oder Umgekehrt, versuchen Sie es mit Ihren eigenen Zeiten.
InformationsquelleAutor der Antwort Stormturtle