Toon posts:

[VB.NET] GDI+ flikkert nog steeds met DoubleBuffer

Pagina: 1
Acties:
  • 224 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Hallo,

Ik ben een programma aan 't maken voor school waarmee we een bal over het scherm moeten laten bewegen, heel simpel. Maar nu wil ik dus zorgen dat het niet meer gaan knipperen, is erg irritant. Nou zocht ik op internet op hoe dat moest en vond ik de volgende 3 magische regels:
Visual Basic:
1
2
3
        Me.SetStyle(ControlStyles.DoubleBuffer, True)
        Me.SetStyle(ControlStyles.UserPaint, True)
        Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)


Er stond bij dat 't in m'n Form_Load moest dus ik heb dat gedaan. Ik heb verder op het scherm een bal en 2 paddles (beetje het Pong idee), dit zijn bitmaps die worden getekent op 't scherm.

Maaarrr, nu wil het nog steeds niet ophouden met flikkeren, hoe los ik het dan op? Zo ziet mijn Form_Load eruit:
Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Box.Width = Me.Width
        Box.Height = Me.Height
        g = Box.CreateGraphics()

        Me.SetStyle(ControlStyles.DoubleBuffer, True)
        Me.SetStyle(ControlStyles.UserPaint, True)
        Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)

        Ball1 = New Ball(20, 0, 20, 3) '(X, Y, Size, Weight)

        Paddle1 = New Paddle("Paddle1.gif", 10, 10) '(Filename, X, Y)
        Paddle2 = New Paddle("Paddle2.gif", 760, 10) '(Filename, X, Y)
    End Sub


Verder staan dus de functies om de bal e.d. te tekenen en te bewegen enzo in een Timer-loop, deze staat op een interval van 14ms. Verder werkt het allemaal prima, behalve dan dat het dubbele bufferen dit schoonheids foutje niet wil verhelpen.

Iemand enig idee?

Alvast bedankt!

[ Voor 3% gewijzigd door Verwijderd op 01-11-2005 20:22 ]


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 26-04 09:25

pjvandesande

GC.Collect(head);

Hoe zie je Paint method er uit? Paint je dingen niet onnodig?

Verwijderd

Topicstarter
Zo ziet het er binnen mijn Ball class uit kwa balletje tekenen:
Visual Basic:
1
2
3
4
5
    Private bal As Bitmap = New Bitmap("bal.gif")

    Public Sub DrawBall(ByVal graph As Graphics)
        graph.DrawImage(bal, ballX, ballY, diameter, diameter)
    End Sub


Binnen de loop wordt Ball1.DrawBall iedere keer aangeroepen om te tekenen.

[ Voor 15% gewijzigd door Verwijderd op 01-11-2005 20:47 ]


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 26-04 09:25

pjvandesande

GC.Collect(head);

Waar haal je je Graphics object vandaan?

En ze de SetStyle is in de ctor. Geen idee of dat verschil maakt, maar daar gooi ik ze eigelijk altijd neer.

Verwijderd

Topicstarter
Ik haal mijn graphics gewoon uit system.drawing.graphics

En wat is de ctor? }:O

[ Voor 20% gewijzigd door Verwijderd op 01-11-2005 21:09 ]


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 26-04 09:25

pjvandesande

GC.Collect(head);

Verwijderd schreef op dinsdag 01 november 2005 @ 21:08:
Ik haal mijn graphics gewoon uit system.drawing.graphics
Waarom doe je dit niet gewoon in het Paint even en gebruik je de Invalide method om een repaint te doen?
Constructor, in VB iets van de New of Init method.

Verwijderd

Topicstarter
Zo werd 't eigenlijk door m'n strot gedouwd door mijn leraar, die zei dat 't enige wat nu nog nodig zou zijn is een DoubleBuffer, toen ben ik dus gaan zoeken en kwam ik met dit :)

Hoe zou ik 't anders in de constructor moeten zetten?

[ Voor 19% gewijzigd door Verwijderd op 01-11-2005 21:17 ]


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 26-04 09:25

pjvandesande

GC.Collect(head);

Verwijderd schreef op dinsdag 01 november 2005 @ 21:15:
Zo werd 't eigenlijk door m'n strot gedouwd door mijn leraar, die zei dat 't enige wat nu nog nodig zou zijn is een DoubleBuffer, toen ben ik dus gaan zoeken en kwam ik met dit :)

Hoe zou ik 't anders in de constructor moeten zetten?
Visual Basic .NET:
1
2
3
4
'constructor
Public Sub New()
     SetStyle(...)
End Sub

Verwijderd

Topicstarter
questa schreef op dinsdag 01 november 2005 @ 21:23:
[...]


Visual Basic .NET:
1
2
3
4
'constructor
Public Sub New()
     SetStyle(...)
End Sub
Oh daaro! Daar had ik 'm al eerder gezet, werkt ook niet :'(

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 26-04 09:25

pjvandesande

GC.Collect(head);

Nee, maar gooi nu is alles in je Paint event.

En dan natuurlijk in je Paint even niet CreateGraphics gebruiken :)

[ Voor 45% gewijzigd door pjvandesande op 01-11-2005 21:34 ]


  • phYzar
  • Registratie: November 2001
  • Laatst online: 20:30
Ik heb onlangs ook gezocht naar hoe (in C# in mijn geval) doublebuffering moet worden gedaan. Ook ik vond daarvoor de in de ts genoemde methode. Die optie werkt nogal slecht...of...naja....niet...

ik heb het zo gedaan: (een usercontrol die ik gebruik om een tekening te laten zien + "animatie")

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class MapViewer : UserControl
{
    private Bitmap doubleBuffer = null;

    public MapViewer() //ctor ;)
    {
    }

    //redraw(-repaint) full view
    private void ReDraw(Graphics g)
    {
        //teken verschillende items op g
        this.DrawMaps(g);
        this.DrawGrid(g);
        this.DrawRoutesMarks(g);
        this.DrawSelectedArea(g);
        this.DrawMeasuredArea(g);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        if(doubleBuffer==null)
        {
            doubleBuffer = new Bitmap(this.Width,this.Height);
        }
        Graphics g = Graphics.FromImage(doubleBuffer);
                
        this.ReDraw(g);
                
        g.Dispose();
                
        e.Graphics.DrawImageUnscaled(doubleBuffer,0,0);
    }
    protected override void OnPaintBackground(PaintEventArgs pevent)
    {
        //Don't allow the background to paint
    }
}


En als ik nu een actie uitvoer die zorgt voor een gewijzigd beeld doe ik:
instantieVanMapViewer.Invalidate();

Werkt goed (weet niet of het de meest efficiente methode is)

(ik hoop dat ik genoeg gecopy-paste heb uit mn code :P)

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

wat je kan doen:
1) teken je oude figuren over in de achtergrondkleur (als mogelijk en het er niet teveel zijn)
2) gebruik zoals hierboven genoemd een bitmap (of gelijke structuur), teken daarin, en blit die dan in je paintbox.

algemene tip:
gebruik de paint-methode van de control, update alles, en roep dan Invalidate() aan.

ASSUME makes an ASS out of U and ME


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 26-04 09:25

pjvandesande

GC.Collect(head);

HIGHGuY schreef op woensdag 02 november 2005 @ 00:07:
algemene tip:
gebruik de paint-methode van de control, update alles, en roep dan Invalidate() aan.
Dit zal al voldoende moeten zijn. Alles drawen op een eigen bitmap geeft bij een enorme afmeting weer gelijk zo'n hamerslag op het geheugen gebruik.

  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 02:20

Rhapsody

In Metal We Trust

In mijn applicatie gebruik ik het volgende:
Visual Basic .NET:
1
2
3
4
5
6
        Me.SetStyle(System.Windows.Forms.ControlStyles.OptimizedDoubleBuffer, True)
        Me.SetStyle(System.Windows.Forms.ControlStyles.AllPaintingInWmPaint, False)
        Me.SetStyle(System.Windows.Forms.ControlStyles.ResizeRedraw, True)
        Me.SetStyle(System.Windows.Forms.ControlStyles.UserPaint, True)
        Me.SetStyle(System.Windows.Forms.ControlStyles.SupportsTransparentBackColor, True)
        MyBase.BackColor = System.Drawing.Color.Transparent


Dit werkt perfect in VB.NET 2005. Deze heb ik in het Load event staan van mijn usercontrol. :)

[ Voor 6% gewijzigd door Rhapsody op 02-11-2005 11:51 ]

🇪🇺 pro Europa!


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 26-04 09:25

pjvandesande

GC.Collect(head);

Rhapsody schreef op woensdag 02 november 2005 @ 11:50:
Dit werkt perfect in VB.NET 2005. Deze heb ik in het Load event staan van mijn usercontrol. :)
Werkt ook gewoon in 1.1, ik denk dat er iets anders aan de hand is. Dat het Paint process gewoon niet goed verloopt.

Het Paint event is hier voor bedoelt en het is mij nog steeds niet duidelijk hoe de TS nou precies de paint uitvoerd. Het kan ook zijn dat er een hoop dubbel werk word uitgevoerd bijvoorbeeld.

Verwijderd

questa schreef op woensdag 02 november 2005 @ 12:00:
[...]

Het Paint event is hier voor bedoeld en het is mij nog steeds niet duidelijk hoe de TS nou precies de paint uitvoert. Het kan ook zijn dat er een hoop dubbel werk wordt uitgevoerd bijvoorbeeld.
Even wat antf****** ;)

De gouden regel is daarnaast; niets tekenen wat je niet ziet.

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 26-04 09:25

pjvandesande

GC.Collect(head);

Verwijderd schreef op woensdag 02 november 2005 @ 12:17:
[...]
De gouden regel is daarnaast; niets tekenen wat je niet ziet.
Hele maal mee eens, hoewel GDI+ zelf slim genoeg is om te herkennen als iets buiten de Clip valt. :Y)
Pagina: 1