Funktionsplotter



  • Wenn du nur ein paar Linien/Flächen malen, oder du dass ein oder Andere Bild auf den Bildschirm klatschen willst, schau dir OnPaint, CPaintDC,CDC an.

    Wenn du Flickerfrei zeichnen willst, must du OnEraseBkgnd überschreiben und einfach immer TRUE zurück geben und alles erst in eine eigene Speicher DC zeichnen und dann alles auf den Zeichenbereich klatschen. CImage erleichtert einem das Erzeugen und handhaben der Speicher-DC's imens.

    Hier im Forum müsste es einige Beispiele dazu geben.





  • Verwegener schrieb:

    Probiers mal hiermit :

    http://fbim.fh-regensburg.de/~saj39122/pgc/ueb/ueb14/ueb14.pdf

    Das hab ich natürlich auch schon gefunden, aber genau zu der Übung gibt es keine Lösung. Alle anderen Übungen habe ich dafür gemacht, aber das hat nichts geholfen, die Übung 14 hab ich einfach nicht hinbekommen.

    Allerdings habe ich es jetzt schon geschafft eine Sinusfunktion zu zeichnen, die jetzt noch an der richtigen Stelle einzubauen wird allerdings wieder schwieriger denke ich. Problem dabei ist, dass ich eigentlich eine Dialoganwendung brauche, da ich Buttons usw. nutzen muss, ich es aber nur geschafft habe in einer SDI zu zeichnen. Da geht das ja relativ leicht, da ich einfach die Koordinaten des Fensters nutze, in einem Dialogfenster kann man sich über GetWindowRect(); ja irgendwie die Größe holen und dann da reinzeichnen, aber das habe ich noch nicht geschafft.



  • Probier's mal mit: GetClientRect
    Die Funktion gibt dir den Bereich ohne Titelleiste, Rahmen,... an in dem gezeichnet werden kann an.
    GetWindowRect, gibt die die Maße mit Titelleiste und Rahmen an.
    Zeichnen kannst du in OnPaint.
    Ein Neuzeichnen löst du folgendermaßen aus:

    Invalidate();
    UpdateWindow();

    Und wie Bernhard schon geschrieben hat, solltest du mit Doppelbuffer arbeiten und OnEraseBckGnd abwürgen.
    Allerdings solltest du in OnEraseBckGnd nicht nur TRUE zurückgeben, sondern auch ein Neuzeichnen auslösen.
    Denn sonst hast du hässliche Ränder wenn du ein anderes Fenster über das Dialogfenster hinwegbewegst.



  • Jetzt mal eine konkrete Frage. Ich habe ein Gruppenfeld in meinen Dialog gezogen und von dem möchte ich jetzt über GetWindowRect(); oder GetClientRect(); die Position und Größe abfragen. In der Übung die ich dazu mache steht dass ich dem Gruppenfeld die IDC_FARBE zuordnen soll, das habe ich gemacht. Dann steht drin dass ich eine Client Variable m_farbe hinzufügen soll. Ich dachte also damit ist eine Member Variable gemeint und habe dann zur IDC_FARBE die Member Variable m_farbe hinzugefügt. Als Kategorie kann ich nur Control und als Variablentyp CButton auswählen, was anderes geht nicht. Wenn ich dann in OnInitialUpdate(); der View Klasse folgendes aufrufe

    GetDlgItem(IDC_FARBE)->GetClientRect(&m_farbe);
    

    und dann kompiliere bekomme ich immer folgenden Fehler.

    "error C2664: 'GetClientRect' : Konvertierung des Parameters 1 von 'class CButton *' in 'struct tagRECT *' nicht moeglich"

    Ich verstehe auch was das Problem ist, aber ich kann ja keinen anderen Typ auswählen für die Variable m_farbe. Kann mir wer erklären was ich falsch mache und wie es richtig geht? Ich habe eigentlich alles genau so gemacht wie es in der Übung angegeben ist, aber es funktioniert nicht.

    @Dialogfensterzeichner
    Wenn ich GetClientRect aufrufe ohne zum Beispiel ein Gruppenfeld zu haben, welchen bereich zum zeichnen gibt er mir denn dann zurück?



  • Hat zu meinem konkreten Problem keiner einen Tip für mich? Ich komm einfach nicht dahinter wie das funktioniert.



  • GetDlgItem(IDC_FARBE)->GetClientRect(&m_farbe);

    und dann kompiliere bekomme ich immer folgenden Fehler.

    "error C2664: 'GetClientRect' : Konvertierung des Parameters 1 von 'class CButton *' in 'struct tagRECT *' nicht moeglich"

    Ich verstehe auch was das Problem ist, aber ich kann ja keinen anderen Typ auswählen für die Variable m_farbe. Kann mir wer erklären was ich falsch mache und wie es richtig geht? Ich habe eigentlich alles genau so gemacht wie es in der Übung angegeben ist, aber es funktioniert nicht.

    Probiers doch mal mit einer Variable vom Typ CRect oder RECT.
    Dann klappt's auch.

    Also:

    //IDC_FARBE -> ID des Element's dessen Position man wissen will
    //cFensterpositionen -> Da wird die Position reingeschreiben
    CRect cFensterpositionen;
    GetDlgItem(IDC_FARBE)->GetClientRect(&cFensterpositionen);
    

    @Dialogfensterzeichner
    Wenn ich GetClientRect aufrufe ohne zum Beispiel ein Gruppenfeld zu haben, welchen bereich zum zeichnen gibt er mir denn dann zurück?

    Ich hoffe du nimmst auch eine Antwort von mir an 😉

    GetClientRect hat nichts mit einem Gruppenfeld oder sonst etwas zu tun.

    GetClientRect gibt dir die Positionsdaten ohne Rahmen, Kanten, Titelleiste,... des gewählten Elementes/Fensters zurück.

    GetWindowRect git dir die Position des gewählten Elementes/Fensters inclusive Rahmen, Titelleiste,... zurück.

    Falls es dir noch nicht bekannt ist: (Fast)Alles was man unter Windows am Bildschirm sieht ist Fenster. -> Daher auch der Name.
    Der Desktop ist ein Fenster. Darauf befindet sich die GUI deines Programm's und dass ist auch ein Fenster. Auf deinem Programm sind Buttons, Eingabefelder,... und dass sind auch Fenster. Und so weiter und so fort.

    Stell dir so ein Fenster einfach mal so wie ein Fenster bei deinem Haus/deiner Wohnung vor.
    Dass Fenster besteht aus einem Rahmen, dem Fensterstock, einer Glasscheibe und eventuell noch über einen Rollladen (Titelleiste).
    GetWindowRect gibt dir die Außenabmessungen des Fensters zurück. Also der gesammte Teil der aus der Mauer raus schaut. Dass bedeutet die Größe und Position mit Fensterstock und Rollladen.

    GetClientRact ist der Bereich in dem man theoretisch neue Fenster einsetzen kann also im Beispiel Fenster beim Haus die Größe und Position der Glasscheibe. Der mit GetClientRect ermittelte Bereich gibt dir also den Bereich an, in dem du mit deinen Fingerfarben (CDC) mahlen kannst ohne dich um den Fensterstock, den Fensterrrahmen oder den Rollladen sorgen machen zu müssen.



  • Hallo Bernhard,

    vielen Dank für deine tolle Antwort.

    Bernhard- schrieb:

    Probiers doch mal mit einer Variable vom Typ CRect oder RECT.
    Dann klappt's auch.

    Das klappt! Ich hatte mich einfach irgendwie davon aufhalten lassen dass mir der Klassenassistent einfach nur eine Variable vom Typ CButton anbieten wollte. Ich hatte gar nicht daran gedacht einfach eine Variable selbst zu deklarieren ohne den Assistenten zu benutzen. Das war natürlich blöd von mir.

    Bernhard- schrieb:

    Falls es dir noch nicht bekannt ist: (Fast)Alles was man unter Windows am Bildschirm sieht ist Fenster. -> Daher auch der Name.

    Mir war natürlich schon bekannt das Windows aus lauter Fenstern besteht, aber ich verdränge einfach immer wieder das sogar ein Button ein Fenster sein soll. Deine Erklärung hat mir sehr geholfen, Danke.

    In der Aufgabe die ich gemacht habe funktioniert übrigens nur GetWindowRect. Bei GetClientRect hat er mir den Zeichenbereich an einer falsche Stelle ausgegeben.

    Also Danke nochmal! 👍



  • Bei GetClientRect hat er mir den Zeichenbereich an einer falsche Stelle ausgegeben

    Nö.
    Dass hat schon seine Richtigkeit.
    Es ist immer eine Frage von wo weg die Positionen gerechnet werden und auf was sich die Maße beziehen.



  • Ja du hast natürlich recht. Ich meinte das es für meine Wünsche an die falsche Stelle gezeichnet wurde. Hätte ich das Koordinatenkreuz an die richtige Stelle verschoben, hätte es so natürlich auch geklappt.

    Ich habe noch mal eine Frage zu der OnPaint Methode. Also ich möchte, wenn auf einen Button geklickt wird, die OnPaint Methode aufrufen. Leider wird die Methode aber schon immer vor dem ersten mal klicken einmal ausgeführt. Wie kann ich das verhindern? Ich habe schon versucht die OnPaint erst in der OnButton zu deklarieren, aber dann bekomme ich einen Fehler. Auch habe ich versucht die Funktion einfach im Header zu deklarieren und dann aufzurufen, aber trotzdem wird immer einmal ausgeführt. Was mache ich da falsch? Hier mal ein Teil meines Codes:

    void CMyDlg::OnButton() 
    {
    	OnPaint();
    	Invalidate(); 
    	UpdateWindow();
    }
    
    void CMyDlg::OnPaint() 
    {
    	CPaintDC dc(this); // device context for painting
    
    	CPen Pen;
    
    	Pen.CreatePen(PS_SOLID,1,RGB(0,0,0));
    	ptrPen=dc.SelectObject(&Pen);
    
    	dc.SetViewportOrg(180,-125);
    
    	dc.MoveTo(0,200);
    	dc.LineTo(0,300);
    	dc.MoveTo(0,300);
    	dc.LineTo(480,300);
    
    	int x[9] = {0};
    	int y[9];
    	CString strData[9];
    	CString strRandData;
    
    	for (int j = 0; j < 9; j++)
    	{
    		y[j] = rand() %2;
    		x[j] = j;
    
    		if(y[j] == 0)
    		{
    			dc.LineTo((x[j]*50),300);
    			dc.LineTo((x[j]*50)+50,300);
    		}
    		else
    		{
    			dc.LineTo(x[j]*50,250);
    			dc.LineTo((x[j]*50)+50,250);
    		}
    	}
    
    	// Kein Aufruf von CDialog::OnPaint() für Zeichnungsnachrichten
    }
    

  • Mod

    Du Windows nicht verstanden. OnPaint wirdimmer automatisch aufgerufen und nicht erst wenn Du irgendwas machst.

    Wenn Du nihct willst das gezeichnet wird, bevor irgendwas passiert ist, dann musst Du eben entsprechende Flags setzen und berücksichtigen.



  • OnPaint darfst man nicht direkt aufrufen!
    Das machst du indirekt indem du Invalidate(); und UpdateWindow(); aufrufst.
    Mit Invalidate sagst du dass der Anzeigebereich deines Programmfensters ncht mehr gültig ist und mit UpdateWindow veranlasst du ein Neuzeichnen -> Indirektes Aufrufen von OnPaint.

    Versuch's doch mal so:
    (Es könnten Fehler enthalten sein, weil ich dass aus dem Gedächtnis geschrieben habe)

    //stdafx.h
    #include "afxstr.h"
    #include "atlimage.h"
    
    //MyDlg.h
    CImage cDisplayImg;
    
    //MyDlg.cpp
    void CMyDlg::OnButton()
    {
        // Wenn schon ein Bild geladen ist -> Speichern und zerstöhren
        if(!cDisplayImg.IsNull())
        {
            cDisplayImg.Save(_T("C:\\Bild.png"));// Bild spechern
            cDisplayImg.Destroy();// Bild zerstöhren
        }
        // Bild neu erstellen
        // X = 600 Pixel
        // Y = 550 Pixel
        // Farbtiefe = 24 Bit
        cDisplayImg.Create(600,550,24);
    
        ZeichneDasZeug();
    
        // Anzeigebereich für ungültig erklähren
        Invalidate();
        // Alles neu zeichnen
        UpdateWindow();
    } 	
    
    void CMyDlg::ZeichneDasZeug()
    {
        // Überprüfen ob ein Bild erzeugt wurde
        if(cDisplayImg.IsNull())
        {
            // Akustisch Bescheid geben dass etwas nicht stimmt
            MessageBeep(MB_ICONERROR);
            return;
        }
        // DC zum malen holen.
        CDC* dc = CDC::FromHandle(cDisplayImg.GetDC());
    
        // Pinsel deffinieren
        CBrush cBrush;
        // Die Farbe Weiß wählen 
        cBrush.CreateSolidBrush(COLORREF(0xFFFFFF));
        CBrush* cOldBrush = dc->SelectObject(&cBrush);
    
        // Den DC-Bereich weiß malen, da sonst alles schwarz ist
        dc->Rectangle(0,0,cDisplayImg.GetWidth(),cDisplayImg.GetHeight());
    
        CPen Pen;
    
        Pen.CreatePen(PS_SOLID,1,RGB(0,0,0));
        CPen* ptrPen=dc->SelectObject(&Pen);
    
    //    dc->SetViewportOrg(180,-125);
    
        // Hier wird lustig gemalt -> Aufpassen dass nicht außerhalb des 
        //                            Zeichenbereichs gemalt wird
        dc->MoveTo(0,200);
        dc->LineTo(0,300);
        dc->MoveTo(0,300);
        dc->LineTo(480,300);
    
        int x= 0;
        int y= 0;
    
        for (int j = 0; j < 9; j++)
        {
            y = rand() %2;
            x = j;
    
            if(y == 0)
            {
                dc->LineTo((x*50),300);
                dc->LineTo((x*50)+50,300);
            }
            else
            {
                dc->LineTo(x*50,250);
                dc->LineTo((x*50)+50,250);
            }
        }
        // Zum Schluss immer Aufräumen
        dc->SelectObject(&cOldBrush);
        dc->SelectObject(&cptrPen);
        // DC der CImage Klasse freigeben, sonst kracht's
        cDisplayImg.ReleaseDC();
    }
    
    void CMyDlg::OnPaint()
    {
        CPaintDC dc(this); // device context for painting
    
        // Überprüfen ob die CImageklasse bereit zum Malen ist
        if(!cDisplayImg.IsNull())
        {
            // Das Bild/die Linien auf den Bildbereich klatschen     
            cDisplayImg.Draw(dc.GetSafeHdc(),0,0);
        }
    
        ///////////////////////////////////////////////////////////////////   
        //  Kein Aufruf von CDialog::OnPaint() für Zeichnungsnachrichten //
        ///////////////////////////////////////////////////////////////////
    }	
    
    BOOL CMyDlg::OnEraseBkgnd()
    {
        // Damit verhindert man das Flickern beim Neuzeichnen
        return TRUE;
    }
    


  • Hallo Bernhard,

    danke auf jeden Fall schonmal für die tolle Antwort. Ich versuche mich da jetzt schon seit ein paar Stunden dran, allerdings ein bisschen anders als du es beschrieben hast. Ich bekomme bei meinem Code aber immer einen Fehler. Hier mal ein paar kurze Ausschnitte meines Codes:

    void CRandomDlg::OnButton() 
    {
    	GraphPaint();
    
    	Invalidate(); 
    	UpdateWindow();
    }
    
    void CRandomDlg::OnPaint() 
    {
    	CPaintDC dc(this); // device context for painting
    
    	// TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen
    
    	CPen Pen;
    
    	// Erzeugen eines neuen Stift
    	Pen.CreatePen(PS_SOLID,1,RGB(0,0,0));
    
    	// Verbinden Stift und Geraet
    	dc.SelectObject(&Pen);
    	dc.SetTextColor(RGB(140,70,0));
    
    	// Koordinatenkreuz zeichnen
    	dc.SetViewportOrg(180,-125);		//Ursprung des Koordinatenkreuzes versetzen
    
    	// x- und y-Achse
    	dc.MoveTo(0,230);
    	dc.LineTo(0,300);
    	dc.MoveTo(0,300);
    	dc.LineTo(930,300);
    
            // Hier zeichne ich einfach ein paar Linien die immer da sein sollten
    
    	// Kein Aufruf von CDialog::OnPaint() für Zeichnungsnachrichten
    }
    
    void CRandomDlg::GraphPaint()
    {
    	CPaintDC dc(this);
    
    	CDC dcgraph;
    	CPen pena;
    
    	dcgraph.SetViewportOrg(180,-125);
    
    	pena.CreatePen(PS_SOLID,1,RGB(255,0,0));
    	dcgraph.SelectObject(&pena);
    	dcgraph.MoveTo(0,300);
    
    	int x[9] = {0};
    	int y[9];
    	CString strData[9];
    
    	for (int j = 0; j < 9; j++)
    	{
    		y[j] = rand() %2;
    		x[j] = j;
    
    		strData[j].Format("%d", y[j]);
    		strRandData += strData[j];
    		m_strRandomData.SetFocus();
    		m_strRandomData.SetSel(strRandData.GetLength());
    		m_strRandomData.ReplaceSel(strRandData, false);
    
    		if(y[j] == 0)
    		{
    			dcgraph.LineTo((x[j]*3),300);
    			dcgraph.LineTo((x[j]*3)+3,300);
    		}
    		else
    		{
    			dcgraph.LineTo(x[j]*3,250);
    			dcgraph.LineTo((x[j]*3)+3,250);
    		}
    
    		Sleep(50);
    	}	 
    }
    

    Tja, ich dachte so müsste es klappen. Ich möchte auch direkt in meinem Dialog zeichnen. Wenn ich alles in der OnPaint aufrufe klappt es auch. Hier hat er irgendwie ein Problem wenn ich "dcgraph.xxx" aufrufe. Sobald ich das in meinem Code drin habe gibt es einen Assert Fehler wenn ich auf meinen Button klicke. Also das Problem muss ja irgendwie an "CDC dcgraph;" liegen. Hast du da eine Idee was ich falsch mache.

    Vielen Dank und viele Grüße
    Laura


  • Mod

    1. CPaintDC darf nur in OnPaint Nachrichten verwendet werden.
    2. Dein CDC dcgraph; ist NULL, d.h. es ist kein KOntext erzeugt.
    3. Wenn Du tatsächlich außerhalb von OnPaint zeichnen musst, dann solltest Du den entsprechenden DC als Zeiger an die Funktion übergeben, wie CView::OnDraw das tut.

    Ansonsten finde ich den Konstrukt etwa unsinnig. in OnButton zu zeichnen. Es muss doch genügen einfach einen Invalidate und UpdateWindow auszuführen. Für was bitte vorher der GraphPaint?



  • Ich hab die GraphPaint() grad mal noch ein bisserl abgeändert. Jetzt kommt kein Fehler mehr, aber es wird auch nichts gezeichnet. Hab auch schon versucht per Invalidate() und UpdateWindow() an diversen Stellen das Zeichnen zu veranlassen, aber das hat auch nicht geklappt.

    void CRandomDlg::GraphPaint()
    {
    	CPaintDC dc(this);
    
    	CPen pena;
    
    	dc.SetViewportOrg(180,-125);
    
    	pena.CreatePen(PS_SOLID,1,RGB(255,0,0));
    	dc.SelectObject(&pena);
    	dc.MoveTo(0,300);
    
    	int x[9] = {0};
    	int y[9];
    	CString strData[9];
    
    	for (int j = 0; j < 9; j++)
    	{
    		y[j] = rand() %2;
    		x[j] = j;
    
    		strData[j].Format("%d", y[j]);
    		strRandData += strData[j];
    		m_strRandomData.SetFocus();
    		m_strRandomData.SetSel(strRandData.GetLength());
    		m_strRandomData.ReplaceSel(strRandData, false);
    
    		if(y[j] == 0)
    		{
    			dc.LineTo((x[j]*3),300);
    			dc.LineTo((x[j]*3)+3,300);
    		}
    		else
    		{
    			dc.LineTo(x[j]*3,250);
    			dc.LineTo((x[j]*3)+3,250);
    		}
    
    		Sleep(50);
    	}	 
    }
    

    Edit: @Martin Richter: haben gleichzeitig gepostet ich werd mir deine Tips also erstmal anschauen



  • Martin Richter schrieb:

    Ansonsten finde ich den Konstrukt etwa unsinnig. in OnButton zu zeichnen. Es muss doch genügen einfach einen Invalidate und UpdateWindow auszuführen. Für was bitte vorher der GraphPaint?

    Also wenn ich das Zeichnen komplett in OnDraw erledige, wird der Graph schon immer gezeichnet wenn ich den Dialog aufrufe. Ich möchte allerdings den Dialog aufrufen, in dem mein Button zu sehen ist und das Koordinatenkreuz und dann wenn man den Button betätigt soll der Graph gezeichnet werden und die Daten in ein Editfeld geschrieben werden.

    Ich habe mir die OnDraw Methode mal angeschaut, allerdings werde ich nicht so ganz schlau draus, was ich dann beim Aufruf übergeben muss. Also einen Zeiger auf irgendwas, aber auf was? Sorry wenn ich mich blöd anstelle, aber ich programmier noch nicht so lange mit MFC.

    Hier noch mal mein neuer Code:

    void CRandomDlg::OnButton() 
    {
    	OnDraw();
    
    	Invalidate(); 
    	UpdateWindow();
    }
    
    void CRandomDlg::OnDraw(CDC *pDC)
    {
    	CPen pena;
    
    	pDC->SetViewportOrg(180,-125);
    
    	pena.CreatePen(PS_SOLID,1,RGB(255,0,0));
    	pDC->SelectObject(&pena);
    	pDC->MoveTo(0,300);
    
    	int x[9] = {0};
    	int y[9];
    	CString strData[9];
    
    	for (int j = 0; j < 9; j++)
    	{
    		y[j] = rand() %2;
    		x[j] = j;
    
    		strData[j].Format("%d", y[j]);
    		strRandData += strData[j];
    		m_strRandomData.SetFocus();
    		m_strRandomData.SetSel(strRandData.GetLength());
    		m_strRandomData.ReplaceSel(strRandData, false);
    
    		if(y[j] == 0)
    		{
    			pDC->LineTo((x[j]*3),300);
    			pDC->LineTo((x[j]*3)+3,300);
    		}
    		else
    		{
    			pDC->LineTo(x[j]*3,250);
    			pDC->LineTo((x[j]*3)+3,250);
    		}
    
    		Sleep(50);
    	}	 
    }
    

  • Mod

    Ich hatte es Dir schon einmal geschrieben:
    1. Verwende ein Flag.
    2. Zeichne nur in OnPaint.
    3. Das Flag setzt Du um, wenn der Button geklickt wird und dann führst Du einen Invalidate/UpdateWindow durch.

    Zu Deinem Code:
    Deine Fehler haben gar nichts mit der MFC zu tun!
    Wieso schreibst Du eine Funktion OnDraw mit einem Argument CDC* und rufst diese Funktion ohne CDC auf?
    Wieso rufst Du überhaupt diese Zeichenfunktion in OnButton auf, wenn Dir schon mehrfach gesagt wurde, dass man nur in OnPaint zeichnet unddass diese Aktion sowieso ungültig wird durch die nächsten Statements?



  • Ich weis einfach nicht wie ich ein Flag setzten kann bzw. wie ich das hier anwenden kann. Wie ich schon geschrieben habe, ich programmiere noch nicht so lange mit MFC und insgesamt auch noch nicht so lange. Ich würde mich sehr freuen wenn du mir ein Beispiel für ein Flag geben könntest. Ich habe schon ein bisschen gegoogelt, aber nichts verständliches gefunden.



  • Also ich hab es jetzt endlich geschafft. Das mit den Flags setzen geht ja eigentlich total einfach, ich hatte es halt einfach nicht unter diesem Namen gekannt. Vielen Dank für die guten Tips.



  • Zeichne nur in OnPaint.

    Warum?
    Ich zeichne immer außerhalb von OnPaint in eine eigene CDC bzw. CImage und kopiere diese dann in OnPaint auf den Anzeigebereich.
    Dadurch fallen Mehrfachberechnungen weg wenn die Ansicht oft neu gezeichnet wird. Und bei langsameren PC's verhindet man damit dass die Linien langsam Stück für Stück einzeln auf den Bildschirm gezeichnet werden.

    Darf ich fragen was ich bei meiner Methode falsch gemacht habe?

    Durch CImage ist der Speicher leicht handzuhaben und das Speichern als Bild benötigt nur eine zusätzliche Zeile.
    Die Positionen der Punkte und Linien werden nur einmal berechnet und beim Zeichnen/Anzeigen gibt es fast keinen zusätzlichen Rechenaufwand.
    Durch Abwürgen des Löschen des Hintergrundes gibt es kein Flickern.
    Man kann alles sehr einfach ein einer Klasse verkapseln und hat beim Wiederverwenden fast keinen Aufwand beim Anpassen.
    Den einzigen Nachteil den ich sehe, ist der etwas höhere Speicherverbrauch.


Anmelden zum Antworten